├── doc ├── .nojekyll ├── logo.png ├── color.css ├── licence.md ├── setup.hpp ├── index.hpp ├── changelog.md ├── base.html ├── layout.xml └── spy.tag ├── logo.png ├── CONTRIBUTORS.md ├── .pre-commit-config.yaml ├── test ├── samples │ ├── posix.cpp │ ├── cuda.cpp │ ├── sycl.cpp │ ├── sanitizers.cpp │ ├── simd-additional.cpp │ ├── stdlib.cpp │ ├── os.cpp │ ├── libc.cpp │ ├── simd.cpp │ ├── data_model.cpp │ ├── simd-arch.cpp │ ├── compiler.cpp │ └── architecture.cpp ├── toolchain │ ├── run_wasm.sh │ ├── run_rvv128.sh │ ├── dpcpp.x86.cmake │ ├── gcc.x86.cmake │ ├── clang.x86.cmake │ ├── gcc.x86_osx.cmake │ ├── dpcpp.sycl.cmake │ ├── gcc.aarch64.cmake │ ├── clang.aarch64.cmake │ ├── gcc.ppc64.cmake │ ├── gcc.aarch64.sve.cmake │ ├── gcc.aarch64.sve2.cmake │ ├── clang.rvv128.cmake │ └── clang.wasm.cmake ├── CMakeLists.txt ├── integration │ ├── main.cpp │ ├── install-test │ │ └── CMakeLists.txt │ ├── cpm-test │ │ └── CMakeLists.txt │ └── fetch-test │ │ └── CMakeLists.txt └── unit │ ├── accelerator.cu │ ├── accelerator.cpp │ ├── stdlib.cpp │ ├── data_model.cpp │ ├── libc.cpp │ ├── arch.cpp │ ├── os.cpp │ ├── compiler.cpp │ └── simd.cpp ├── test_package ├── example.cpp ├── CMakeLists.txt └── conanfile.py ├── .gitignore ├── include └── spy │ ├── simd │ ├── wasm.hpp │ ├── riscv.hpp │ ├── ppc.hpp │ ├── arm.hpp │ └── x86.hpp │ ├── spy.hpp │ ├── detail.hpp │ ├── types.hpp │ ├── accelerator.hpp │ ├── sanitizers.hpp │ ├── data_model.hpp │ ├── stdlib.hpp │ ├── arch.hpp │ ├── os.hpp │ ├── libc.hpp │ ├── compiler.hpp │ └── simd.hpp ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ ├── documentation.yml │ ├── package-standalone.yml │ ├── integration.yml │ └── unit.yml ├── appveyor.yml ├── cmake ├── spy-config.cmake ├── compiler.cmake └── dependencies.cmake ├── LICENSE.md ├── README.md ├── CMakeLists.txt └── .clang-format /doc/.nojekyll: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfalcou/spy/HEAD/logo.png -------------------------------------------------------------------------------- /doc/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfalcou/spy/HEAD/doc/logo.png -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # List of contributors 2 | 3 | ## Main Team 4 | FALCOU Joel 5 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/mirrors-clang-format 3 | rev: v19.1.7 4 | hooks: 5 | - id: clang-format 6 | types_or: [c++] -------------------------------------------------------------------------------- /test/samples/posix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | if constexpr( spy::supports::posix_ ) 7 | { 8 | std::cout << "This is a POSIX platform.\n"; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/samples/cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | if constexpr( spy::supports::cuda ) std::cout << "Compiling with CUDA supports\n"; 7 | else std::cout << "No accelerator supports\n"; 8 | } 9 | -------------------------------------------------------------------------------- /test/samples/sycl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main() 6 | { 7 | if constexpr( spy::supports::sycl ) std::cout << "Compiling with SYCL supports.\n"; 8 | else std::cout << "No accelerator supports\n"; 9 | } 10 | -------------------------------------------------------------------------------- /test/toolchain/run_wasm.sh: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | #!/bin/sh 7 | 8 | node $@ 9 | -------------------------------------------------------------------------------- /test/toolchain/run_rvv128.sh: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | #!/bin/sh 7 | 8 | qemu-riscv64 --cpu rv64,v=true,vlen=128 $@ 9 | -------------------------------------------------------------------------------- /test/toolchain/dpcpp.x86.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_C_COMPILER icpx ) 7 | set(CMAKE_CXX_COMPILER icpx ) 8 | -------------------------------------------------------------------------------- /test/toolchain/gcc.x86.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_C_COMPILER gcc-14 ) 7 | set(CMAKE_CXX_COMPILER g++-14 ) 8 | -------------------------------------------------------------------------------- /test/toolchain/clang.x86.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_C_COMPILER clang ) 7 | set(CMAKE_CXX_COMPILER clang++ ) 8 | -------------------------------------------------------------------------------- /test/toolchain/gcc.x86_osx.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_C_COMPILER gcc-12 ) 7 | set(CMAKE_CXX_COMPILER g++-12 ) 8 | -------------------------------------------------------------------------------- /doc/color.css: -------------------------------------------------------------------------------- 1 | html 2 | { 3 | /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ 4 | --primary-dark-color: hsl(165, 95%, 20%); 5 | --primary-color: hsl(165, 95%, 30%); 6 | --primary-light-color: hsl(165, 95%, 40%); 7 | 8 | /* page base colors */ 9 | --page-background-color: white; 10 | --page-foreground-color: hsl(165, 95%, 10%); 11 | --page-secondary-foreground-color: hsl(165, 95%, 20%); 12 | } 13 | -------------------------------------------------------------------------------- /test_package/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::cout << spy::operating_system << std::endl; 7 | std::cout << spy::architecture << std::endl; 8 | std::cout << spy::simd_instruction_set << std::endl; 9 | std::cout << spy::compiler << std::endl; 10 | std::cout << spy::libc << std::endl; 11 | std::cout << spy::stdlib << std::endl; 12 | } 13 | -------------------------------------------------------------------------------- /test/toolchain/dpcpp.sycl.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_C_COMPILER icpx ) 7 | set(CMAKE_CXX_COMPILER icpx ) 8 | 9 | set(CMAKE_CXX_FLAGS "-fsycl" ) 10 | -------------------------------------------------------------------------------- /test/samples/sanitizers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::cout << "Address sanitizers status: " 7 | << std::boolalpha << spy::supports::address_sanitizers_status 8 | << "\n"; 9 | 10 | std::cout << "Threads sanitizers status: " 11 | << std::boolalpha << spy::supports::thread_sanitizers_status 12 | << "\n"; 13 | 14 | std::cout << "Any sanitizers status: " 15 | << std::boolalpha << spy::supports::sanitizers_status << "\n"; 16 | } 17 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | copa_setup_test_targets() 7 | set(root "${CMAKE_SOURCE_DIR}/test") 8 | copa_glob_unit(QUIET PATTERN "unit/*.cpp" INTERFACE spy_tests) 9 | copa_glob_unit(QUIET PATTERN "samples/*.cpp" INTERFACE spy_tests) 10 | -------------------------------------------------------------------------------- /test/samples/simd-additional.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | if constexpr( spy::supports::fma_ ) std::cout << "This code has been compiled with FMA3 support.\n"; 7 | else if constexpr( spy::supports::fma4_ ) std::cout << "This code has been compiled with FMA4 support.\n"; 8 | else if constexpr( spy::supports::xop_ ) std::cout << "This code has been compiled with XOP support.\n"; 9 | else if constexpr( spy::supports::avx512::cd_ ) std::cout << "This code has been compiled with AV512-CD support.\n"; 10 | } 11 | -------------------------------------------------------------------------------- /test/samples/stdlib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | // Comparisons 7 | if constexpr( spy::stdlib == spy::gnucpp_ ) std::cout << "This code is compiled with the GNU stdlib.\n"; 8 | else if constexpr( spy::stdlib == spy::libcpp_ ) std::cout << "This code is compiled with the Clang stdlib.\n"; 9 | 10 | // Direct test 11 | if constexpr( spy::gnucpp_ ) std::cout << "This code is compiled with the GNU stdlib.\n"; 12 | else if constexpr( spy::libcpp_ ) std::cout << "This code is compiled with the Clang stdlib.\n"; 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # Backup 31 | *~ 32 | *_ 33 | *# 34 | 35 | # Setup 36 | .idea/ 37 | *.sublime-* 38 | 39 | # Potential local build repository 40 | *build*/ 41 | Testing/ 42 | .vscode/ 43 | .cache 44 | compile_commands.json 45 | -------------------------------------------------------------------------------- /test/toolchain/gcc.aarch64.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_SYSTEM_NAME Linux) 7 | set(CMAKE_SYSTEM_PROCESSOR arm) 8 | 9 | set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc-14 ) 10 | set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++-14 ) 11 | 12 | set(CMAKE_CROSSCOMPILING_CMD qemu-aarch64) 13 | -------------------------------------------------------------------------------- /test/toolchain/clang.aarch64.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_SYSTEM_PROCESSOR arm ) 7 | 8 | set(CMAKE_C_COMPILER /opt/homebrew/opt/llvm@15/bin/clang ) 9 | set(CMAKE_CXX_COMPILER /opt/homebrew/opt/llvm@15/bin/clang++ ) 10 | 11 | set(CMAKE_CXX_FLAGS " -DEVE_NO_FORCEINLINE ${EVE_OPTIONS}" ) -------------------------------------------------------------------------------- /test/integration/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::cout << "OS : " << spy::operating_system << std::endl; 7 | std::cout << "CPU Architecture : " << spy::architecture << std::endl; 8 | std::cout << "SIMD Instructions : " << spy::simd_instruction_set << std::endl; 9 | std::cout << "Compiler : " << spy::compiler << std::endl; 10 | std::cout << "libc version : " << spy::libc << std::endl; 11 | std::cout << "libstd : " << spy::stdlib << std::endl; 12 | } 13 | -------------------------------------------------------------------------------- /test_package/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | project(PackageTest CXX) 3 | 4 | include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) 5 | conan_basic_setup() 6 | 7 | add_library(spy_config INTERFACE) 8 | target_compile_features ( spy_config INTERFACE cxx_std_20 ) 9 | 10 | add_executable(example example.cpp) 11 | target_link_libraries(example ${CONAN_LIBS} PUBLIC spy_config) 12 | 13 | # CTest is a testing tool that can be used to test your project. 14 | # enable_testing() 15 | # add_test(NAME example 16 | # WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin 17 | # COMMAND example) 18 | -------------------------------------------------------------------------------- /test/toolchain/gcc.ppc64.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_SYSTEM_NAME Linux ) 7 | set(CMAKE_SYSTEM_PROCESSOR powerpc ) 8 | 9 | set(CMAKE_C_COMPILER powerpc64-linux-gnu-gcc-14 ) 10 | set(CMAKE_CXX_COMPILER powerpc64-linux-gnu-g++-14 ) 11 | set(CMAKE_CXX_FLAGS "-static" ) 12 | 13 | set(CMAKE_CROSSCOMPILING_CMD qemu-ppc64) 14 | -------------------------------------------------------------------------------- /test/toolchain/gcc.aarch64.sve.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_SYSTEM_NAME Linux) 7 | set(CMAKE_SYSTEM_PROCESSOR arm) 8 | 9 | set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc-14 ) 10 | set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++-14 ) 11 | set(CMAKE_CXX_FLAGS "-march=armv8-a+sve -msve-vector-bits=512" ) 12 | 13 | set(CMAKE_CROSSCOMPILING_CMD qemu-aarch64) 14 | -------------------------------------------------------------------------------- /test/toolchain/gcc.aarch64.sve2.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_SYSTEM_NAME Linux) 7 | set(CMAKE_SYSTEM_PROCESSOR arm) 8 | 9 | set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc-14 ) 10 | set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++-14 ) 11 | set(CMAKE_CXX_FLAGS "-march=armv8-a+sve2 -msve-vector-bits=512" ) 12 | 13 | set(CMAKE_CROSSCOMPILING_CMD qemu-aarch64) 14 | -------------------------------------------------------------------------------- /include/spy/simd/wasm.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | #if !defined(SPY_SIMD_DETECTED) && defined(__wasm_simd128__) 11 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::simd128_ 12 | #endif 13 | 14 | #if defined(SPY_SIMD_DETECTED) && !defined(SPY_SIMD_VENDOR) 15 | #define SPY_SIMD_IS_WASM 16 | #define SPY_SIMD_VENDOR ::spy::_::simd_isa::wasm_ 17 | #endif 18 | -------------------------------------------------------------------------------- /test/integration/install-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | cmake_minimum_required(VERSION 3.22) 7 | project(spy-install-test LANGUAGES CXX) 8 | enable_testing() 9 | 10 | find_package(spy CONFIG REQUIRED) 11 | add_executable(test_spy ../main.cpp) 12 | target_link_libraries(test_spy PUBLIC spy::spy) 13 | add_test(NAME test_spy COMMAND test_spy) 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /test/samples/os.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | // Comparisons 7 | if constexpr( spy::operating_system == spy::bsd_ ) std::cout << "This code runs on BSD.\n"; 8 | else if constexpr( spy::operating_system == spy::linux_ ) std::cout << "This code runs on Linux.\n"; 9 | else if constexpr( spy::operating_system == spy::windows_ ) std::cout << "This code runs on Windows.\n"; 10 | 11 | // Direct test 12 | if constexpr( spy::bsd_ ) std::cout << "This code runs on BSD.\n"; 13 | else if constexpr( spy::linux_ ) std::cout << "This code runs on Linux.\n"; 14 | else if constexpr( spy::windows_ ) std::cout << "This code runs on Windows.\n"; 15 | } 16 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | ## ------------------------------------------------------------------------------------------------- 2 | ## SPY - C++ Informations Broker 3 | ## Copyright: SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ## ------------------------------------------------------------------------------------------------- 6 | version: 1.0.{build} 7 | os: Visual Studio 2019 8 | 9 | environment: 10 | matrix: 11 | - ARCH: x86 12 | 13 | build_script: 14 | - mkdir build 15 | - cd build 16 | - cmake -G "Visual Studio 16 2019" -A x64 .. 17 | - cmake --build . --target unit --verbose --config Release 18 | - cmake --build . --target unit --verbose --config Debug 19 | 20 | test_script: 21 | - ctest -C Release -VV 22 | - ctest -C Debug -VV 23 | -------------------------------------------------------------------------------- /test/toolchain/clang.rvv128.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_SYSTEM_NAME Generic) 7 | set(CMAKE_SYSTEM_PROCESSOR riscv64) 8 | 9 | set(CMAKE_C_COMPILER clang ) 10 | set(CMAKE_CXX_COMPILER clang++ ) 11 | 12 | set(CMAKE_CXX_FLAGS "-O3 -march=rv64gcv -std=c++20 -mrvv-vector-bits=128 --static --target=riscv64-unknown-linux-gnu ${EVE_OPTIONS}" ) 13 | set(CMAKE_CROSSCOMPILING_CMD ${PROJECT_SOURCE_DIR}/test/toolchain/run_rvv128.sh ) 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. A Compiler Explorer link is the preferred way to transfer buggy code fragment. Code must be as small as possible while still exhibiting the bug. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Setup:** 20 | - Compiler and compiler's version: [e.g. g++ 10] 21 | - OS: [e.g. Arch Linux] 22 | 23 | **Additional context** 24 | Add any other context about the problem here. 25 | -------------------------------------------------------------------------------- /test/samples/libc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | // Comparisons 7 | if constexpr( spy::libc == spy::gnu_ ) std::cout << "This code is compiled with the GNU libc.\n"; 8 | else if constexpr( spy::libc == spy::zos_ ) std::cout << "This code is compiled with the zOS libc.\n"; 9 | else if constexpr( spy::libc == spy::vms_ ) std::cout << "This code is compiled with the VMS libc.\n"; 10 | 11 | // Direct test 12 | if constexpr( spy::gnu_ ) std::cout << "This code is compiled with the GNU libc.\n"; 13 | else if constexpr( spy::zos_ ) std::cout << "This code is compiled with the zOS libc.\n"; 14 | else if constexpr( spy::vms_ ) std::cout << "This code is compiled with the VMS libc.\n"; 15 | } 16 | -------------------------------------------------------------------------------- /test/samples/simd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::cout << spy::simd_instruction_set << "\n"; 7 | 8 | if constexpr( spy::simd_instruction_set == spy::avx_ ) 9 | { 10 | std::cout << "This code has been compiled with AVX instructions set.\n"; 11 | } 12 | 13 | if constexpr( spy::simd_instruction_set >= spy::sse41_ ) 14 | { 15 | std::cout << "This code has been compiled with at least support for SSE 4.1\n"; 16 | } 17 | 18 | if constexpr( spy::simd_instruction_set <= spy::sse2_ ) 19 | { 20 | std::cout << "This code has been compiled with support for SSE2 at most.\n"; 21 | } 22 | 23 | std::cout << "This code can use " << spy::simd_instruction_set.width << " bits register.\n"; 24 | } 25 | -------------------------------------------------------------------------------- /cmake/spy-config.cmake: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | 7 | ##====================================================================================================================== 8 | ## Reuse install.cmake to preapre package properly 9 | ##====================================================================================================================== 10 | include("${CMAKE_CURRENT_LIST_DIR}/spy-targets.cmake") 11 | set(SPY_LIBRARIES spy::spy) 12 | -------------------------------------------------------------------------------- /test/samples/data_model.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | // Comparisons 7 | if constexpr( spy::data_model == spy::ilp32_ ) std::cout << "This code is compiled on a ILP32 system\n"; 8 | else if constexpr( spy::data_model == spy::ilp64_ ) std::cout << "This code is compiled on a ILP64 system\n"; 9 | else if constexpr( spy::data_model == spy::lp64_ ) std::cout << "This code is compiled on a LP64 system\n"; 10 | 11 | // Direct test 12 | if constexpr( spy::ilp32_ ) std::cout << "This code is compiled on a ILP32 system\n"; 13 | else if constexpr( spy::ilp64_ ) std::cout << "This code is compiled on a ILP64 system\n"; 14 | else if constexpr( spy::lp64_ ) std::cout << "This code is compiled on a LP64 system\n"; 15 | } 16 | -------------------------------------------------------------------------------- /test/samples/simd-arch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | if constexpr( spy::simd_instruction_set == spy::x86_simd_ ) 7 | { 8 | std::cout << "This code has been compiled with some Intel SIMD instructions set.\n"; 9 | } 10 | 11 | if constexpr( spy::simd_instruction_set == spy::arm_simd_ ) 12 | { 13 | std::cout << "This code has been compiled with some ARM SIMD instructions set.\n"; 14 | } 15 | 16 | if constexpr( spy::simd_instruction_set == spy::ppc_simd_ ) 17 | { 18 | std::cout << "This code has been compiled with some Power PC SIMD instructions set.\n"; 19 | } 20 | 21 | if constexpr( spy::simd_instruction_set == spy::wasm_simd_ ) 22 | { 23 | std::cout << "This code has been compiled with WASM enabled.\n"; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test_package/conanfile.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from conans import ConanFile, CMake, tools 4 | 5 | 6 | class SpyTestConan(ConanFile): 7 | settings = "os", "compiler", "build_type", "arch" 8 | generators = "cmake" 9 | 10 | def build(self): 11 | cmake = CMake(self) 12 | # Current dir is "test_package/build/" and CMakeLists.txt is 13 | # in "test_package" 14 | cmake.configure() 15 | cmake.build() 16 | 17 | def imports(self): 18 | self.copy("*.dll", dst="bin", src="bin") 19 | self.copy("*.dylib*", dst="bin", src="lib") 20 | self.copy('*.so*', dst='bin', src='lib') 21 | 22 | def test(self): 23 | if not tools.cross_building(self.settings): 24 | os.chdir("bin") 25 | self.run(".%sexample" % os.sep) 26 | -------------------------------------------------------------------------------- /include/spy/simd/riscv.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | #if defined(__riscv_vector) 11 | // Flexible RISC-V Vector has no __riscv_v_fixed_vlen defined 12 | #if !defined(__riscv_v_fixed_vlen) 13 | #define SPY_SIMD_IS_RISCV_FLEXIBLE_RVV 14 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::rvv_ 15 | // Fixed-size RISC-V Vector has __riscv_v_fixed_vlen 16 | #else 17 | #define SPY_SIMD_IS_RISCV_FIXED_RVV 18 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::fixed_rvv_ 19 | #endif 20 | #endif 21 | 22 | #if defined(__riscv_vector) 23 | #define SPY_SIMD_IS_RISCV_RVV 24 | #define SPY_SIMD_VENDOR ::spy::_::simd_isa::riscv_ 25 | #endif 26 | -------------------------------------------------------------------------------- /test/toolchain/clang.wasm.cmake: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | set(CMAKE_C_COMPILER emcc ) 7 | set(CMAKE_CXX_COMPILER em++ ) 8 | 9 | ## We do test exceptions 10 | set(CMAKE_CXX_FLAGS "-fexceptions -msimd128" ) 11 | 12 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 13 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 14 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 15 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 16 | 17 | set(ECMASCRIPT_ROOT get_filename_component(${CMAKE_CXX_COMPILER})) 18 | 19 | set(CMAKE_FIND_ROOT_PATH "$ENV{EMSDK}/upstream/emscripten/cache/sysroot/") 20 | 21 | set(CMAKE_CROSSCOMPILING_CMD ${PROJECT_SOURCE_DIR}/test/toolchain/run_wasm.sh ) 22 | -------------------------------------------------------------------------------- /test/samples/compiler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | // Comparisons 7 | if constexpr( spy::compiler == spy::gcc_ ) std::cout << "This code compiled with g++.\n"; 8 | else if constexpr( spy::compiler == spy::clang_ ) std::cout << "This code compiled with clang.\n"; 9 | else if constexpr( spy::compiler == spy::dpcpp_ ) std::cout << "This code compiled with ICPX.\n"; 10 | 11 | // Direct test 12 | if constexpr( spy::gcc_ ) std::cout << "This code compiled with g++.\n"; 13 | else if constexpr( spy::clang_ ) std::cout << "This code compiled with clang.\n"; 14 | else if constexpr( spy::dpcpp_ ) std::cout << "This code compiled with ICPX.\n"; 15 | 16 | //Version checks 17 | using namespace spy::literal; 18 | if constexpr( spy::compiler == 16'0_clang ) std::cout << "This code compiled with clang 16.\n"; 19 | if constexpr( spy::compiler >= 15'0_clang ) std::cout << "This code compiled with clang 15 or ulterior.\n"; 20 | } 21 | -------------------------------------------------------------------------------- /test/integration/cpm-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | cmake_minimum_required(VERSION 3.18) 7 | project(spy-cpm-test LANGUAGES CXX) 8 | enable_testing() 9 | 10 | message(STATUS "Testing CPM for branch ${GIT_BRANCH}") 11 | 12 | # Setup CPM 13 | include(cpm.cmake) 14 | 15 | # Add dependencies 16 | CPMAddPackage ( NAME spy 17 | GIT_REPOSITORY "https://github.com/jfalcou/spy.git" 18 | GIT_TAG "${GIT_BRANCH}" 19 | OPTIONS "SPY_BUILD_TEST OFF" 20 | ) 21 | 22 | # Use spy 23 | add_executable(test_spy ../main.cpp) 24 | target_link_libraries(test_spy PUBLIC spy::spy) 25 | add_test(NAME test_spy COMMAND test_spy) 26 | -------------------------------------------------------------------------------- /test/integration/fetch-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | cmake_minimum_required(VERSION 3.22) 7 | project(spy-fetch-test LANGUAGES CXX) 8 | enable_testing() 9 | 10 | message(STATUS "Testing FetchContent for branch ${GIT_BRANCH}") 11 | 12 | # Enable FetchContent 13 | include(FetchContent) 14 | 15 | # Retrieve SPY from relative git directory 16 | FetchContent_Declare(spy 17 | GIT_REPOSITORY "https://github.com/jfalcou/spy.git" 18 | GIT_TAG ${GIT_BRANCH} 19 | ) 20 | 21 | # make available 22 | FetchContent_MakeAvailable(spy) 23 | 24 | add_executable(test_spy ../main.cpp) 25 | target_link_libraries(test_spy PUBLIC spy::spy) 26 | add_test(NAME test_spy COMMAND test_spy) 27 | -------------------------------------------------------------------------------- /test/samples/architecture.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | // Comparisons 7 | if constexpr( spy::architecture == spy::x86_ ) std::cout << "This code is compiled for X86.\n"; 8 | else if constexpr( spy::architecture == spy::amd64_ ) std::cout << "This code is compiled for X86-64.\n"; 9 | else if constexpr( spy::architecture == spy::ppc_ ) std::cout << "This code is compiled for PowerPC.\n"; 10 | else if constexpr( spy::architecture == spy::arm_ ) std::cout << "This code is compiled for ARM.\n"; 11 | else if constexpr( spy::architecture == spy::riscv_ ) std::cout << "This code is compiled for RISC-V.\n"; 12 | 13 | // Direct test 14 | if constexpr( spy::x86_ ) std::cout << "This code is compiled for X86.\n"; 15 | else if constexpr( spy::amd64_ ) std::cout << "This code is compiled for X86-64.\n"; 16 | else if constexpr( spy::ppc_ ) std::cout << "This code is compiled for PowerPC.\n"; 17 | else if constexpr( spy::arm_ ) std::cout << "This code is compiled for ARM.\n"; 18 | else if constexpr( spy::riscv_ ) std::cout << "This code is compiled for RISC-V.\n"; 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/documentation.yml: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | name: SPY Documentation Generation 7 | on: 8 | push: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | generate-doc: 14 | runs-on: ubuntu-latest 15 | container: 16 | image: ghcr.io/jfalcou/compilers:v9 17 | strategy: 18 | fail-fast: false 19 | steps: 20 | - name: Fetch current branch 21 | uses: actions/checkout@v4.1.1 22 | - name: Prepare SPY 23 | run: | 24 | mkdir build && cd build 25 | cmake .. -G Ninja -DSPY_BUILD_TEST=OFF -DSPY_BUILD_DOCUMENTATION=ON 26 | 27 | - name: Generate Doxygen 28 | run: | 29 | cd build 30 | ninja spy-doxygen 31 | 32 | - name: Deploy to gh-pages 33 | uses: peaceiris/actions-gh-pages@v3 34 | with: 35 | github_token: ${{ secrets.GITHUB_TOKEN }} 36 | publish_dir: ./build/doc 37 | -------------------------------------------------------------------------------- /test/unit/accelerator.cu: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | 11 | int main() 12 | { 13 | std::cout << "Check that specified accelerator is supported: " << std::endl; 14 | { 15 | #if defined(SYCL_LANGUAGE_VERSION) && defined (__INTEL_LLVM_COMPILER) 16 | static_assert( spy::supports::sycl ); 17 | std::cout << "Currently compiling with " << spy::supports::sycl << " enabled\n"; 18 | #else 19 | static_assert( !spy::supports::sycl ); 20 | std::cout << "Currently compiling without SYCL enabled\n"; 21 | #endif 22 | } 23 | { 24 | #if defined (__CUDACC__) 25 | static_assert( spy::supports::cuda ); 26 | std::cout << "Currently compiling with " << spy::supports::cuda << " enabled\n"; 27 | #else 28 | static_assert( !spy::supports::cuda ); 29 | std::cout << "Currently compiling without CUDA enabled\n"; 30 | #endif 31 | } 32 | std::cout << "Done." << std::endl; 33 | } 34 | -------------------------------------------------------------------------------- /test/unit/accelerator.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | 11 | int main() 12 | { 13 | std::cout << "Check that specified accelerator is supported: " << std::endl; 14 | { 15 | #if defined(SYCL_LANGUAGE_VERSION) && defined (__INTEL_LLVM_COMPILER) 16 | static_assert( spy::supports::sycl ); 17 | std::cout << "Currently compiling with " << spy::supports::sycl << " enabled\n"; 18 | #else 19 | static_assert( !spy::supports::sycl ); 20 | std::cout << "Currently compiling without SYCL enabled\n"; 21 | #endif 22 | } 23 | { 24 | #if defined(__NVCC__) && defined (__CUDACC__) 25 | static_assert( spy::supports::cuda ); 26 | std::cout << "Currently compiling with " << spy::supports::cuda << " enabled\n"; 27 | #else 28 | static_assert( !spy::supports::cuda ); 29 | std::cout << "Currently compiling without CUDA enabled\n"; 30 | #endif 31 | } 32 | std::cout << "Done." << std::endl; 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Boost Software License 1.0 2 | 3 | Copyright : SPY Project Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the 6 | software and accompanying documentation covered by this license (the "Software") to use, reproduce, 7 | display, distribute, execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the 9 | following: 10 | 11 | The copyright notices in the Software and this entire statement, including the above license grant, 12 | this restriction and the following disclaimer, must be included in all copies of the Software, in 13 | whole or in part, and all derivative works of the Software, unless such copies or derivative works 14 | are solely in the form of machine-executable object code generated by a source language processor. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 17 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 18 | NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE 19 | BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SPY Library logo 2 | 3 | # C++ Informations Broker 4 | 5 | [![Licence](https://img.shields.io/github/license/jfalcou/spy?style=plastic)](https://img.shields.io/github/license/jfalcou/spy?style=plastic) 6 | [![Discord](https://img.shields.io/discord/692734675726237696?style=plastic)](https://discord.gg/a9qVaEMeXd8) 7 | 8 | 9 | # Purpose 10 | Detection and versioning of operating systems, compilers, architecture and other elements are 11 | traditionally done using preprocessor macros. Library like 12 | [Boost.Predef](https://www.boost.org/doc/libs/release/doc/html/predef.html) provides a sanitized 13 | interface on top of those, but still lives in a world where the preprocessor is king. 14 | 15 | SPY is a C++20 (and onward) library that gathers similar information and provides a `constexpr` 16 | compatible interface to access that information, thus making their exploitation within `constexpr` 17 | context possible. 18 | 19 | The complete [documentation can be found here](https://jfalcou.github.io/spy). 20 | 21 | # Useful Links 22 | - [Our CppCon 2019 Ligthning talk slides](https://docs.google.com/presentation/d/1nSBhU4pr5EWznni0MYsyDkMCr3O3q2XS-KQdz2_BRRI/edit?usp=sharing) 23 | - [Our CppCon 2019 Ligthning talk video](https://www.youtube.com/watch?v=t406o2EhG-A) 24 | - [Boost.Predef](https://www.boost.org/doc/libs/release/doc/html/predef.html) 25 | -------------------------------------------------------------------------------- /cmake/compiler.cmake: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | 7 | ##====================================================================================================================== 8 | ## Compiler options for Tests 9 | ##====================================================================================================================== 10 | add_library(spy_tests INTERFACE) 11 | 12 | target_compile_features ( spy_tests INTERFACE cxx_std_20 ) 13 | 14 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 15 | if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") 16 | target_compile_options( spy_tests INTERFACE /W3 /EHsc ) 17 | else() 18 | target_compile_options( spy_tests INTERFACE -Werror -Wall -Wextra -Wunused-variable -Wshadow -Wdocumentation) 19 | endif() 20 | elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 21 | target_compile_options( spy_tests INTERFACE /W3 /EHsc /Zc:preprocessor) 22 | else() 23 | target_compile_options( spy_tests INTERFACE -Werror -Wall -Wextra -Wunused-variable -Wshadow) 24 | endif() 25 | 26 | target_include_directories( spy_tests INTERFACE 27 | ${PROJECT_SOURCE_DIR}/test 28 | ${PROJECT_SOURCE_DIR}/include 29 | ) 30 | -------------------------------------------------------------------------------- /doc/licence.md: -------------------------------------------------------------------------------- 1 | Licence {#licence} 2 | ======= 3 | 4 | This library is licensed under the [Boost Software License](http://opensource.org/licenses/MIT): 5 | 6 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | Copyright : SPY Project Contributors 8 | 9 | Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the 10 | software and accompanying documentation covered by this license (the "Software") to use, reproduce, 11 | display, distribute, execute, and transmit the Software, and to prepare derivative works of the 12 | Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the 13 | following: 14 | 15 | The copyright notices in the Software and this entire statement, including the above license grant, 16 | this restriction and the following disclaimer, must be included in all copies of the Software, in 17 | whole or in part, and all derivative works of the Software, unless such copies or derivative works 18 | are solely in the form of machine-executable object code generated by a source language processor. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 22 | NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE 23 | BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | -------------------------------------------------------------------------------- /test/unit/stdlib.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | #include 11 | 12 | int main() 13 | { 14 | std::cout << "Check that detected stdlib is correct: " << std::flush; 15 | { 16 | #if defined(_LIBCPP_VERSION) 17 | { 18 | assert( spy::stdlib == spy::libcpp_ ); 19 | assert( !(spy::stdlib == spy::gnucpp_)); 20 | } 21 | #elif defined(__GLIBCXX__) 22 | { 23 | assert( !(spy::stdlib == spy::libcpp_)); 24 | assert( spy::stdlib == spy::gnucpp_ ); 25 | } 26 | #endif 27 | } 28 | std::cout << "Done." << std::endl; 29 | std::cout << "Detected stdlib: " << spy::stdlib << std::endl; 30 | 31 | std::cout << "Check that detected constexpr selection on exact stdlib is correct: " << std::flush; 32 | { 33 | using namespace spy::literal; 34 | 35 | #if defined(_LIBCPP_VERSION) 36 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_libcpp; 37 | #elif defined(__GLIBCXX__) 38 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_gnucpp; 39 | #else 40 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = false; 41 | #endif 42 | 43 | if constexpr(spy::stdlib) 44 | { 45 | assert( !bool(wrong_constexpr_behavior) ); 46 | } 47 | else 48 | { 49 | assert( bool(wrong_constexpr_behavior) ); 50 | } 51 | } 52 | std::cout << "Done." << std::endl; 53 | } 54 | -------------------------------------------------------------------------------- /.github/workflows/package-standalone.yml: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | name: SPY Documentation Generation 7 | on: 8 | push: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | package-standalone: 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: write 17 | pull-requests: write 18 | container: 19 | image: ghcr.io/jfalcou/compilers:v9 20 | strategy: 21 | fail-fast: false 22 | steps: 23 | - name: Fetch current branch 24 | uses: actions/checkout@v4.1.1 25 | 26 | - name: Configure SPY 27 | run: | 28 | git config --global --add safe.directory /__w/spy/spy 29 | mkdir build && cd build 30 | cmake .. -G Ninja -DSPY_BUILD_TEST=OFF -DSPY_BUILD_DOCUMENTATION=OFF 31 | 32 | - name: Generate standalone SPY header 33 | run: | 34 | cd build && ninja spy-standalone 35 | 36 | - name: Update standalone branch 37 | run: | 38 | git fetch origin 39 | git config --global user.email "spy@nowhere.com" 40 | git config --global user.name "SPY Standalone Generator" 41 | git checkout standalone 42 | cp build/spy.hpp spy.hpp 43 | git add spy.hpp 44 | git commit --allow-empty -m "Latest SPY standalone" 45 | 46 | - name: Push changes 47 | uses: ad-m/github-push-action@master 48 | with: 49 | github_token: ${{ secrets.GITHUB_TOKEN }} 50 | branch: "standalone" -------------------------------------------------------------------------------- /cmake/dependencies.cmake: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | 7 | ##====================================================================================================================== 8 | ## Download and setup CPM 9 | ##====================================================================================================================== 10 | set(CPM_DOWNLOAD_VERSION 0.40.2) 11 | 12 | if(CPM_SOURCE_CACHE) 13 | set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 14 | elseif(DEFINED ENV{CPM_SOURCE_CACHE}) 15 | set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 16 | else() 17 | set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 18 | endif() 19 | 20 | if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) 21 | message(STATUS "[${PROJECT_NAME}] Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") 22 | file(DOWNLOAD 23 | https://github.com/TheLartians/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake 24 | ${CPM_DOWNLOAD_LOCATION} 25 | ) 26 | endif() 27 | 28 | include(${CPM_DOWNLOAD_LOCATION}) 29 | 30 | ##====================================================================================================================== 31 | ## Retrieve dependencies 32 | ##====================================================================================================================== 33 | CPMAddPackage(NAME COPACABANA GITHUB_REPOSITORY jfalcou/copacabana GIT_TAG main) 34 | -------------------------------------------------------------------------------- /test/unit/data_model.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | #include 11 | 12 | int main() 13 | { 14 | std::cout << "Check that detected data model is correct: " << std::endl; 15 | { 16 | #if defined(__LP64__) || defined(_LP64) 17 | assert( !(spy::data_model == spy::ilp32_)); 18 | assert( !(spy::data_model == spy::lp32_ )); 19 | assert( !(spy::data_model == spy::silp64_ )); 20 | assert( !(spy::data_model == spy::ilp64_)); 21 | assert( !(spy::data_model == spy::llp64_)); 22 | assert( spy::data_model == spy::lp64_ ); 23 | #endif 24 | 25 | #if defined(__ILP32__) || defined(_ILP32) 26 | assert( spy::data_model == spy::ilp32_ ); 27 | assert( !(spy::data_model == spy::lp32_ )); 28 | assert( !(spy::data_model == spy::silp64_ )); 29 | assert( !(spy::data_model == spy::ilp64_)); 30 | assert( !(spy::data_model == spy::llp64_)); 31 | assert( !(spy::data_model == spy::lp64_ )); 32 | #endif 33 | 34 | std::cout << "ILP32 status: " << std::boolalpha << (spy::data_model == spy::ilp32_ ) << std::endl; 35 | std::cout << "LP32 status: " << std::boolalpha << (spy::data_model == spy::lp32_ ) << std::endl; 36 | std::cout << "SILP64 status: " << std::boolalpha << (spy::data_model == spy::silp64_) << std::endl; 37 | std::cout << "ILP64 status: " << std::boolalpha << (spy::data_model == spy::ilp64_ ) << std::endl; 38 | std::cout << "LLP64 status: " << std::boolalpha << (spy::data_model == spy::llp64_ ) << std::endl; 39 | std::cout << "LP64 status: " << std::boolalpha << (spy::data_model == spy::lp64_ ) << std::endl; 40 | } 41 | std::cout << "Done." << std::endl; 42 | std::cout << "Data model detected: " << spy::data_model << std::endl; 43 | } 44 | -------------------------------------------------------------------------------- /include/spy/simd/ppc.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | #if !defined(SPY_SIMD_DETECTED) && defined(__VSX__) 11 | #define SPY_SIMD_IS_PPC_VSX 12 | #if defined(_ARCH_PWR10) 13 | #define SPY_SIMD_IS_PPC_VSX_3_01 14 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vsx_3_01_ 15 | #elif defined(_ARCH_PWR9) 16 | #define SPY_SIMD_IS_PPC_VSX_3_00 17 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vsx_3_00_ 18 | #elif defined(_ARCH_PWR8) 19 | #define SPY_SIMD_IS_PPC_VSX_2_07 20 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vsx_2_07_ 21 | #elif defined(_ARCH_PWR7) 22 | #define SPY_SIMD_IS_PPC_VSX_2_06 23 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vsx_2_06_ 24 | #endif 25 | #endif 26 | 27 | #if !defined(SPY_SIMD_DETECTED) && (defined(__ALTIVEC__) || defined(__VEC__)) 28 | #define SPY_SIMD_IS_PPC_VMX 29 | #if defined(_ARCH_PWR10) 30 | #define SPY_SIMD_IS_PPC_VMX_3_01 31 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vmx_3_01_ 32 | #elif defined(_ARCH_PWR9) 33 | #define SPY_SIMD_IS_PPC_VMX_3_00 34 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vmx_3_00_ 35 | #elif defined(_ARCH_PWR8) 36 | #define SPY_SIMD_IS_PPC_VMX_2_07 37 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vmx_2_07_ 38 | #elif defined(_ARCH_PWR7) 39 | #define SPY_SIMD_IS_PPC_VMX_2_06 40 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vmx_2_06_ 41 | #elif defined(_ARCH_PWR6) 42 | #define SPY_SIMD_IS_PPC_VMX_2_05 43 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vmx_2_05_ 44 | #elif defined(_ARCH_PWR5) 45 | #define SPY_SIMD_IS_PPC_VMX_2_03 46 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vmx_2_03_ 47 | #endif 48 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::vmx_ 49 | #endif 50 | 51 | #if defined(SPY_SIMD_DETECTED) && !defined(SPY_SIMD_VENDOR) 52 | #define SPY_SIMD_IS_PPC 53 | #define SPY_SIMD_VENDOR ::spy::_::simd_isa::ppc_ 54 | #endif 55 | -------------------------------------------------------------------------------- /include/spy/spy.hpp: -------------------------------------------------------------------------------- 1 | //====================================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //====================================================================================================================== 8 | #ifndef SPY_SPY_HPP_INCLUDED 9 | #define SPY_SPY_HPP_INCLUDED 10 | 11 | //====================================================================================================================== 12 | //! @namespace spy 13 | //! @brief Main SPY namespace 14 | //====================================================================================================================== 15 | namespace spy 16 | { 17 | //==================================================================================================================== 18 | //! @defgroup api Main API 19 | //==================================================================================================================== 20 | 21 | //==================================================================================================================== 22 | //! @namespace supports 23 | //! @brief Support detection SPY namespace 24 | //==================================================================================================================== 25 | namespace supports 26 | { 27 | } 28 | 29 | //==================================================================================================================== 30 | //! @namespace literal 31 | //! @brief SPY User-defined literal namespace 32 | //==================================================================================================================== 33 | namespace literal 34 | { 35 | } 36 | } 37 | 38 | #include 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /.github/workflows/integration.yml: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | name: SPY Integration Tests 7 | on: 8 | push: 9 | branches: 10 | - main 11 | 12 | concurrency: 13 | group: spy-integration-${{ github.ref }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | 18 | install: 19 | runs-on: [ubuntu-latest] 20 | container: 21 | image: ghcr.io/jfalcou/compilers:v9 22 | strategy: 23 | fail-fast: false 24 | 25 | steps: 26 | - name: Fetch current branch 27 | uses: actions/checkout@v4.1.1 28 | - name: Install SPY from checkout 29 | run: | 30 | mkdir build && cd build 31 | cmake -G Ninja .. -DSPY_BUILD_TEST=OFF -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS="-std=c++20" 32 | ninja install 33 | - name: Run Sample CMake 34 | run: | 35 | mkdir install && cd install 36 | cmake ../test/integration/install-test -G Ninja -DCMAKE_CXX_FLAGS="-std=c++20" 37 | ninja && ctest --verbose 38 | 39 | fetch-content: 40 | env: 41 | BRANCH_NAME: ${{ github.head_ref || github.ref_name }} 42 | runs-on: [ubuntu-latest] 43 | container: 44 | image: ghcr.io/jfalcou/compilers:v9 45 | strategy: 46 | fail-fast: false 47 | 48 | steps: 49 | - name: Fetch current branch 50 | uses: actions/checkout@v4.1.1 51 | - name: Compile using FetchContent 52 | run: | 53 | git config --global --add safe.directory /__w/kumi/kumi 54 | mkdir install && cd install 55 | cmake ../test/integration/fetch-test -G Ninja -DGIT_BRANCH=${BRANCH_NAME} -DSPY_BUILD_TEST=OFF -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS="-std=c++20" 56 | ninja && ctest --verbose 57 | 58 | cpm: 59 | env: 60 | BRANCH_NAME: ${{ github.head_ref || github.ref_name }} 61 | runs-on: [ubuntu-latest] 62 | container: 63 | image: ghcr.io/jfalcou/compilers:v9 64 | strategy: 65 | fail-fast: false 66 | 67 | steps: 68 | - name: Fetch current branch 69 | uses: actions/checkout@v4.1.1 70 | - name: Compile using CPM 71 | run: | 72 | git config --global --add safe.directory /__w/kumi/kumi 73 | mkdir install && cd install 74 | cmake ../test/integration/cpm-test -G Ninja -DGIT_BRANCH=${BRANCH_NAME} -DCMAKE_CXX_FLAGS="-std=c++20" -DCMAKE_CXX_COMPILER=clang++ -DSPY_BUILD_TEST=OFF 75 | ninja && ctest --verbose 76 | -------------------------------------------------------------------------------- /include/spy/detail.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace spy::_ 13 | { 14 | template 15 | concept stream = requires(T& os, char c) { 16 | { os.copyfmt(os) }; 17 | { os.flush() }; 18 | { os.put(c) }; 19 | }; 20 | 21 | template constexpr int find(int i0) 22 | { 23 | int sz = sizeof...(c); 24 | char arr[] = {c...}; 25 | while (i0 < sz && arr[i0] != '\'') ++i0; 26 | return i0; 27 | } 28 | 29 | template constexpr int parse(int i0, int i1) 30 | { 31 | char arr[] = {c...}; 32 | int value = 0; 33 | while (i0 < i1 && arr[i0] != '\'') value = value * 10 + (arr[i0++] - 48); 34 | return value; 35 | } 36 | 37 | template class Wrapper, char... c> constexpr auto literal_wrap() 38 | { 39 | constexpr int b0 = 0, e0 = find(0); 40 | constexpr int b1 = e0 + 1, e1 = find(b1); 41 | constexpr int b2 = e1 + 1, e2 = sizeof...(c); 42 | 43 | return Wrapper(b0, e0), parse(b1, e1), parse(b2, e2)>{}; 44 | } 45 | 46 | template struct version_id 47 | { 48 | static constexpr int major = M; 49 | static constexpr int minor = N; 50 | static constexpr int patch = P; 51 | }; 52 | 53 | template 54 | constexpr bool operator==(version_id, version_id) noexcept 55 | { 56 | return (M1 == M2) && (N1 == N2) && (P1 == P2); 57 | } 58 | 59 | template 60 | constexpr std::strong_ordering operator<=>(version_id, version_id) noexcept 61 | { 62 | if constexpr (constexpr auto cmp0 = M1 <=> M2; cmp0 != 0) return cmp0; 63 | else if constexpr (constexpr auto cmp1 = N1 <=> N2; cmp1 != 0) return cmp1; 64 | else return P1 <=> P2; 65 | } 66 | 67 | template constexpr inline version_id version = {}; 68 | 69 | using unspecified_version_t = version_id<-1, 0, 0>; 70 | constexpr inline unspecified_version_t unspecified_version = {}; 71 | 72 | template<_::stream OS, int M, int N, int P> auto& operator<<(OS& os, version_id const&) 73 | { 74 | return os << "v" << M << "." << N << "." << P; 75 | } 76 | 77 | template<_::stream OS> auto& operator<<(OS& os, unspecified_version_t const&) 78 | { 79 | return os << "(unspecified)"; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /include/spy/types.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | #if defined(SPY_ARCH_IS_ARM) 11 | #if defined(__ARM_FP16_FORMAT_IEEE) && __ARM_FP16_FORMAT_IEEE == 1 \ 12 | && (!defined(__ARM_FP16_FORMAT_ALTERNATIVE) || __ARM_FP16_FORMAT_ALTERNATIVE == 0) 13 | #define SPY_SUPPORTS_FP16_TYPE 14 | 15 | #if defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC) 16 | #define SPY_SUPPORTS_FP16_SCALAR_OPS 17 | #endif 18 | 19 | #if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) 20 | #define SPY_SUPPORTS_FP16_VECTOR_OPS 21 | #define SPY_SUPPORTS_FP16_VECTOR_CONVERSION 22 | #elif defined(__aarch64__) 23 | #define SPY_SUPPORTS_FP16_VECTOR_CONVERSION 24 | #endif 25 | #endif 26 | #elif defined(SPY_ARCH_IS_X86) 27 | #define SPY_SUPPORTS_FP16_TYPE 28 | #elif defined(SPY_ARCH_IS_AMD64) 29 | #define SPY_SUPPORTS_FP16_TYPE 30 | 31 | #if defined(__AVX512FP16__) 32 | #define SPY_SUPPORTS_FP16_SCALAR_OPS 33 | #define SPY_SUPPORTS_FP16_VECTOR_OPS 34 | #define SPY_SUPPORTS_FP16_VECTOR_CONVERSION 35 | #elif defined(__F16C__) 36 | #define SPY_SUPPORTS_FP16_VECTOR_CONVERSION 37 | #endif 38 | #elif defined(SPY_ARCH_IS_RISCV) 39 | #define SPY_SUPPORTS_FP16_TYPE 40 | 41 | #if defined(__riscv_zfh) 42 | #define SPY_SUPPORTS_FP16_SCALAR_OPS 43 | #endif 44 | 45 | #if defined(__riscv_zvfh) 46 | #define SPY_SUPPORTS_FP16_VECTOR_OPS 47 | #define SPY_SUPPORTS_FP16_VECTOR_CONVERSION 48 | #elif defined(__riscv_zvfhmin) 49 | #define SPY_SUPPORTS_FP16_VECTOR_CONVERSION 50 | #endif 51 | #endif 52 | 53 | namespace spy::supports::fp16 54 | { 55 | //! Whether the _Float16 type is provided by the compiler on the current platform. 56 | #ifdef SPY_SUPPORTS_FP16_TYPE 57 | static constexpr bool type = true; 58 | #else 59 | static constexpr bool type = false; 60 | #endif 61 | 62 | //! Whether the current architecture supports scalar operations on IEEE-754 half-precision floating-point numbers. 63 | #ifdef SPY_SUPPORTS_FP16_SCALAR_OPS 64 | static constexpr bool scalar_ops = true; 65 | #else 66 | static constexpr bool scalar_ops = false; 67 | #endif 68 | 69 | //! Whether the current architecture supports packed conversion operations between IEEE-754 half-precision 70 | //! floating-point numbers and at least one other IEEE-754 floating-point type. 71 | #ifdef SPY_SUPPORTS_FP16_VECTOR_CONVERSION 72 | static constexpr bool vector_conversion = true; 73 | #else 74 | static constexpr bool vector_conversion = false; 75 | #endif 76 | 77 | //! Whether the current architecture supports vector operations on IEEE-754 half-precision floating-point numbers. 78 | #ifdef SPY_SUPPORTS_FP16_VECTOR_OPS 79 | static constexpr bool vector_ops = true; 80 | #else 81 | static constexpr bool vector_ops = false; 82 | #endif 83 | } 84 | -------------------------------------------------------------------------------- /test/unit/libc.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | #include 11 | 12 | int main() 13 | { 14 | std::cout << "Check that detected libc is correct: " << std::flush; 15 | { 16 | #if defined(__cloudlibc__) 17 | assert( spy::libc == spy::cloudabi_ ); 18 | assert( !(spy::libc == spy::uc_ )); 19 | assert( !(spy::libc == spy::vms_ )); 20 | assert( !(spy::libc == spy::zos_ )); 21 | assert( !(spy::libc == spy::gnu_ )); 22 | #elif defined(__UCLIBC__) 23 | assert( !(spy::libc == spy::cloudabi_ )); 24 | assert( spy::libc == spy::uc_ ); 25 | assert( !(spy::libc == spy::vms_ )); 26 | assert( !(spy::libc == spy::zos_ )); 27 | assert( !(spy::libc == spy::gnu_ )); 28 | #elif defined(__CRTL_VER) 29 | assert( !(spy::libc == spy::cloudabi_ )); 30 | assert( !(spy::libc == spy::uc_ )); 31 | assert( spy::libc == spy::vms_ ); 32 | assert( !(spy::libc == spy::zos_ )); 33 | assert( !(spy::libc == spy::gnu_ )); 34 | #elif defined(__LIBREL__) 35 | assert( !(spy::libc == spy::cloudabi_ )); 36 | assert( !(spy::libc == spy::uc_ )); 37 | assert( !(spy::libc == spy::vms_ )); 38 | assert( spy::libc == spy::zos_ ); 39 | assert( !(spy::libc == spy::gnu_ )); 40 | #elif defined(__GLIBC__) || defined(__GNU_LIBRARY__) 41 | assert( !(spy::libc == spy::cloudabi_) ); 42 | assert( !(spy::libc == spy::uc_ ) ); 43 | assert( !(spy::libc == spy::vms_ ) ); 44 | assert( !(spy::libc == spy::zos_ ) ); 45 | assert( spy::libc == spy::gnu_ ); 46 | #else 47 | assert( !(spy::libc == spy::cloudabi_) ); 48 | assert( !(spy::libc == spy::uc_ ) ); 49 | assert( !(spy::libc == spy::vms_ ) ); 50 | assert( !(spy::libc == spy::zos_ ) ); 51 | assert( !(spy::libc == spy::gnu_ ) ); 52 | #endif 53 | } 54 | std::cout << "Done." << std::endl; 55 | std::cout << "Detected libc: " << spy::libc << std::endl; 56 | 57 | std::cout << "Check that detected constexpr selection on exact libc is correct: " << std::flush; 58 | { 59 | using namespace spy::literal; 60 | 61 | #if defined(__cloudlibc__) 62 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_cloud; 63 | #elif defined(__UCLIBC__) 64 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_uc; 65 | #elif defined(__CRTL_VER) 66 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_vms; 67 | #elif defined(__LIBREL__) 68 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_zos; 69 | #elif defined(__GLIBC__) || defined(__GNU_LIBRARY__) 70 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_gnu; 71 | #else 72 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = false; 73 | #endif 74 | 75 | if constexpr(spy::libc) 76 | { 77 | assert( !bool(wrong_constexpr_behavior) ); 78 | } 79 | else 80 | { 81 | assert( bool(wrong_constexpr_behavior) ); 82 | } 83 | } 84 | std::cout << "Done." << std::endl; 85 | } 86 | -------------------------------------------------------------------------------- /include/spy/simd/arm.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | #if defined(__ARM_FEATURE_SVE2) 11 | // Flexible SVE2 has no SVE_BITS or SVE_BITS set at 0 and is set via -march=armv8-a+sve 12 | #if !defined(__ARM_FEATURE_SVE_BITS) || (__ARM_FEATURE_SVE_BITS == 0) 13 | #define SPY_SIMD_IS_ARM_FLEXIBLE_SVE2 14 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::sve2_ 15 | // Fixed-size SVE has SVE_BITS set at expected size via -msve-vector-bits 16 | #elif defined(__ARM_FEATURE_SVE_BITS) 17 | #if (__ARM_FEATURE_SVE_BITS == 128) 18 | #define SPY_SIMD_IS_ARM_FIXED_SVE2 19 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::fixed_sve2_ 20 | #elif (__ARM_FEATURE_SVE_BITS == 256) 21 | #define SPY_SIMD_IS_ARM_FIXED_SVE2 22 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::fixed_sve2_ 23 | #elif (__ARM_FEATURE_SVE_BITS == 512) 24 | #define SPY_SIMD_IS_ARM_FIXED_SVE2 25 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::fixed_sve2_ 26 | #elif (__ARM_FEATURE_SVE_BITS == 1024) 27 | #define SPY_SIMD_IS_ARM_FIXED_SVE2 28 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::fixed_sve2_ 29 | #else 30 | #error "[SPY] - No support for non-power of 2 SVE-2 cardinals" 31 | #endif 32 | #endif 33 | #endif 34 | 35 | #if !defined(SPY_SIMD_DETECTED) && defined(__ARM_FEATURE_SVE) 36 | // Flexible SVE has no SVE_BITS or SVE_BITS set at 0 and is set via -march=armv8-a+sve 37 | #if !defined(__ARM_FEATURE_SVE_BITS) || (__ARM_FEATURE_SVE_BITS == 0) 38 | #define SPY_SIMD_IS_ARM_FLEXIBLE_SVE 39 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::sve_ 40 | // Fixed-size SVE has SVE_BITS set at expected size via -msve-vector-bits 41 | #elif defined(__ARM_FEATURE_SVE_BITS) 42 | #if (__ARM_FEATURE_SVE_BITS == 128) 43 | #define SPY_SIMD_IS_ARM_FIXED_SVE 44 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::fixed_sve_ 45 | #elif (__ARM_FEATURE_SVE_BITS == 256) 46 | #define SPY_SIMD_IS_ARM_FIXED_SVE 47 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::fixed_sve_ 48 | #elif (__ARM_FEATURE_SVE_BITS == 512) 49 | #define SPY_SIMD_IS_ARM_FIXED_SVE 50 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::fixed_sve_ 51 | #elif (__ARM_FEATURE_SVE_BITS == 1024) 52 | #define SPY_SIMD_IS_ARM_FIXED_SVE 53 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::fixed_sve_ 54 | #else 55 | #error "[SPY] - No support for non-power of 2 SVE cardinals" 56 | #endif 57 | #endif 58 | #endif 59 | 60 | #if defined(__ARM_FEATURE_SVE2) 61 | #define SPY_SIMD_IS_ARM_SVE2 62 | #define SPY_SIMD_VENDOR ::spy::_::simd_isa::arm_sve_ 63 | #elif defined(__ARM_FEATURE_SVE) 64 | #define SPY_SIMD_IS_ARM_SVE 65 | #define SPY_SIMD_VENDOR ::spy::_::simd_isa::arm_sve_ 66 | #endif 67 | 68 | #if !defined(SPY_SIMD_DETECTED) && defined(__aarch64__) 69 | #define SPY_SIMD_IS_ARM_ASIMD 70 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::asimd_ 71 | #endif 72 | 73 | #if !defined(SPY_SIMD_DETECTED) && ((defined(__ARM_NEON__) || defined(_M_ARM)) && (__ARM_ARCH == 7)) 74 | #define SPY_SIMD_IS_ARM_NEON 75 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::neon_ 76 | #endif 77 | 78 | #if defined(SPY_SIMD_DETECTED) && !defined(SPY_SIMD_VENDOR) 79 | #define SPY_SIMD_IS_ARM 80 | #define SPY_SIMD_VENDOR ::spy::_::simd_isa::arm_ 81 | #endif 82 | -------------------------------------------------------------------------------- /include/spy/accelerator.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | namespace spy::supports 11 | { 12 | template struct sycl_t 13 | { 14 | explicit constexpr operator bool() const noexcept { return M > 0 && N > 0; } 15 | 16 | template<_::stream OS> friend auto& operator<<(OS& os, sycl_t) 17 | { 18 | os << "SYCL v" << M << '.' << N; 19 | if (P > 0) os << '.' << P; 20 | return os; 21 | } 22 | 23 | template constexpr inline bool operator==(sycl_t const&) const noexcept 24 | { 25 | return M == M1 && N == N1 && P == P1; 26 | } 27 | }; 28 | 29 | template struct cuda_t 30 | { 31 | explicit constexpr operator bool() const noexcept { return M > 0 && N > 0; } 32 | 33 | template constexpr inline bool operator==(cuda_t const&) const noexcept 34 | { 35 | return M == M1 && N == N1 && P == P1; 36 | } 37 | 38 | template<_::stream OS> friend auto& operator<<(OS& os, cuda_t) 39 | { 40 | #if defined(__NVCC__) 41 | os << "NVCC "; 42 | #elif defined(__clang__) 43 | os << "Clang "; 44 | #endif 45 | 46 | os << "CUDA v" << M << '.' << N; 47 | if (P > 0) os << '.' << P; 48 | return os; 49 | } 50 | }; 51 | 52 | #if defined(SYCL_LANGUAGE_VERSION) && defined(__INTEL_LLVM_COMPILER) 53 | #define SPY_ACCELERATOR_SUPPORTS_SYCL 54 | constexpr inline auto sycl = sycl_t{}; 55 | #elif defined(SPY_DOXYGEN_INVOKED) 56 | //================================================================================================ 57 | //! @ingroup api 58 | //! @brief SYCL usage indicator. 59 | //! 60 | //! Retrieves the information about wether or not current file is compiled with SYCL supports. 61 | //! 62 | //! @groupheader{Example} 63 | //! @godbolt{samples/sycl.cpp} 64 | //================================================================================================ 65 | constexpr inline auto sycl = **implementation - defined * *; 66 | 67 | #else 68 | constexpr inline auto sycl = sycl_t<-1, -1, -1>{}; 69 | #endif 70 | 71 | #if defined(__CUDACC__) 72 | #if defined(__CUDACC_VER_MAJOR__) 73 | #define SPY_ACCELERATOR_SUPPORTS_CUDA 74 | constexpr inline auto cuda = cuda_t<__CUDACC_VER_MAJOR__, __CUDACC_VER_MINOR__, 0>{}; 75 | #elif defined(CUDA_VERSION) 76 | #define SPY_ACCELERATOR_SUPPORTS_CUDA 77 | constexpr inline auto cuda = cuda_t{}; 78 | #endif 79 | #elif defined(SPY_DOXYGEN_INVOKED) 80 | //================================================================================================ 81 | //! @ingroup api 82 | //! @brief CUDA usage indicator. 83 | //! 84 | //! Retrieves the information about wether or not current file is compiled using NVCC. 85 | //! Note that this indicator works in both .cpp and .cu files. 86 | //! 87 | //! @groupheader{Example} 88 | //! @godbolt{samples/cuda.cpp} 89 | //================================================================================================ 90 | constexpr inline auto cuda = **implementation - defined * *; 91 | #else 92 | constexpr inline auto cuda = cuda_t<-1, -1, -1>{}; 93 | #endif 94 | } 95 | -------------------------------------------------------------------------------- /include/spy/sanitizers.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | #include 10 | 11 | // Clang detection 12 | #if defined(__has_feature) 13 | #if __has_feature(address_sanitizer) 14 | #define SPY_ADDRESS_SANITIZERS_ENABLED 15 | #endif 16 | #if __has_feature(thread_sanitizer) 17 | #define SPY_THREAD_SANITIZERS_ENABLED 18 | #endif 19 | #endif 20 | 21 | // g++/MSVC detection 22 | #if !defined(SPY_ADDRESS_SANITIZERS_ENABLED) 23 | #if defined(__SANITIZE_ADDRESS__) 24 | #define SPY_ADDRESS_SANITIZERS_ENABLED 25 | #endif 26 | #endif 27 | 28 | #if !defined(SPY_THREAD_SANITIZERS_ENABLED) 29 | #if defined(__SANITIZE_THREAD__) 30 | #define SPY_THREAD_SANITIZERS_ENABLED 31 | #endif 32 | #endif 33 | 34 | namespace spy::supports 35 | { 36 | #if defined(SPY_ADDRESS_SANITIZERS_ENABLED) 37 | constexpr bool address_sanitizers_status = true; 38 | #elif defined(SPY_DOXYGEN_INVOKED) 39 | //================================================================================================== 40 | //! @ingroup api 41 | //! @brief Thread sanitizer status indicator. 42 | //! 43 | //! Indicate if current code is compile using `-fsanitize=address`. 44 | //! 45 | //! @groupheader{Example} 46 | //! @godbolt{samples/sanitizers.cpp} 47 | //================================================================================================== 48 | constexpr bool address_sanitizers_status = **implementation - specified * *; 49 | #else 50 | constexpr bool address_sanitizers_status = false; 51 | #endif 52 | 53 | #if defined(SPY_THREAD_SANITIZERS_ENABLED) 54 | constexpr bool thread_sanitizers_status = true; 55 | #elif defined(SPY_DOXYGEN_INVOKED) 56 | //================================================================================================== 57 | //! @ingroup api 58 | //! @brief Thread sanitizer status indicator. 59 | //! 60 | //! Indicate if current code is compile using `-fsanitize=threads`. 61 | //! 62 | //! @groupheader{Example} 63 | //! @godbolt{samples/sanitizers.cpp} 64 | //================================================================================================== 65 | constexpr bool thread_sanitizers_status = **implementation - specified * *; 66 | #else 67 | constexpr bool thread_sanitizers_status = false; 68 | #endif 69 | 70 | //================================================================================================== 71 | //! @ingroup api 72 | //! @brief Sanitizers status indicator. 73 | //! 74 | //! Aggregate the status of all detected sanitizers 75 | //! 76 | //! @groupheader{Example} 77 | //! @godbolt{samples/sanitizers.cpp} 78 | //================================================================================================== 79 | constexpr bool sanitizers_status = address_sanitizers_status || thread_sanitizers_status; 80 | } 81 | 82 | #if defined(SPY_COMPILER_IS_CLANG) || defined(SPY_COMPILER_IS_GCC) 83 | #define SPY_DISABLE_ADDRESS_SANITIZERS __attribute__((no_sanitize_address)) 84 | #define SPY_DISABLE_THREAD_SANITIZERS __attribute__((no_sanitize_thread)) 85 | #elif defined(SPY_COMPILER_IS_MSVC) 86 | #define SPY_DISABLE_ADDRESS_SANITIZERS __declspec(no_sanitize_address) 87 | #define SPY_DISABLE_THREAD_SANITIZERS 88 | #else 89 | #define SPY_DISABLE_ADDRESS_SANITIZERS 90 | #define SPY_DISABLE_THREAD_SANITIZERS 91 | #endif 92 | 93 | #define SPY_DISABLE_SANITIZERS SPY_DISABLE_ADDRESS_SANITIZERS SPY_DISABLE_THREAD_SANITIZERS 94 | -------------------------------------------------------------------------------- /include/spy/data_model.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | namespace spy::_ 11 | { 12 | template struct data_model_info 13 | { 14 | inline constexpr explicit operator bool() const noexcept; 15 | 16 | template 17 | constexpr bool operator==(data_model_info const&) const noexcept 18 | { 19 | return (Short == Short2) && (Integer == Integer2) && (Long == Long2) && (Pointer == Pointer2); 20 | } 21 | }; 22 | 23 | template<_::stream OS, int Short, int Integer, int Long, int Pointer> 24 | auto& operator<<(OS& os, data_model_info const&) 25 | { 26 | if constexpr (Pointer == 4 && Integer == 4) return os << "ILP32"; 27 | else if constexpr (Pointer == 4 && Integer == 2) return os << "LP32"; 28 | else if constexpr (Pointer == 8 && Long == 8 && Integer == 8 && Short == 8) return os << "IntegerLP64"; 29 | else if constexpr (Pointer == 8 && Short == 8 && Integer == 8 && Short == 2) return os << "ILP64"; 30 | else if constexpr (Pointer == 8 && Long == 4 && Integer == 8 && Short == 2) return os << "LLP64"; 31 | else if constexpr (Pointer == 8 && Long == 8 && Integer == 4 && Short == 2) return os << "LP64"; 32 | else return os << "Unknown data model"; 33 | } 34 | } 35 | 36 | namespace spy 37 | { 38 | using data_model_type = _::data_model_info; 39 | 40 | //================================================================================================ 41 | //! @ingroup api 42 | //! @brief Data Model reporting value 43 | //! 44 | //! The `spy::data_model` object can be compared to any other data model related value to verify 45 | //! if the code being compiled for a specific data model 46 | //! 47 | //! Additionally, any of the data model related value are convertible to `bool`. They evaluates to `true` if they 48 | //! matches the correct data model currently used. 49 | //! 50 | //! @groupheader{Supported Value} 51 | //! 52 | //! Name | Data Model 53 | //! --------------| ------------- 54 | //! `spy::ilp32` | ILP32 55 | //! `spy::lp32` | LP32 56 | //! `spy::silp64` | SILP64 57 | //! `spy::ilp64` | ILP64 58 | //! `spy::llp64` | LLP64 59 | //! `spy::lp64` | LP64 60 | //! 61 | //! @groupheader{Example} 62 | //! @godbolt{samples/data_model.cpp} 63 | //================================================================================================ 64 | constexpr inline auto data_model = data_model_type{}; 65 | } 66 | 67 | namespace spy::_ 68 | { 69 | template 70 | inline constexpr data_model_info::operator bool() const noexcept 71 | { 72 | return spy::data_model == *this; 73 | } 74 | } 75 | 76 | namespace spy 77 | { 78 | //================================================================================================ 79 | // Data model detector stand-alone instances 80 | //================================================================================================ 81 | constexpr inline auto ilp32_ = _::data_model_info<2, 4, sizeof(long), 4>{}; 82 | constexpr inline auto lp32_ = _::data_model_info<2, 2, sizeof(long), 4>{}; 83 | constexpr inline auto silp64_ = _::data_model_info<8, 8, 8, 8>{}; 84 | constexpr inline auto ilp64_ = _::data_model_info<2, 8, 8, 8>{}; 85 | constexpr inline auto llp64_ = _::data_model_info<2, 8, 4, 8>{}; 86 | constexpr inline auto lp64_ = _::data_model_info<2, 4, 8, 8>{}; 87 | } 88 | -------------------------------------------------------------------------------- /doc/setup.hpp: -------------------------------------------------------------------------------- 1 | #error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY 2 | 3 | //================================================================================================== 4 | /** 5 | @page setup Setup 6 | 7 | @tableofcontents 8 | 9 | @section setup-source Install from the source 10 | 11 | Code source of **SPY** is available on GitHub and can be retrieved via the following command: 12 | 13 | @code 14 | $ git clone https://github.com/jfalcou/spy.git 15 | @endcode 16 | 17 | Once retrieved, you should have a `spy` folder which contains the whole source code. 18 | 19 | Create a `build` directory here and enter it. Once in the `build` directory, 20 | you can use **CMake** to generate the build system for **SPY**. We recommend using 21 | Ninja but any build system is fine. 22 | 23 | @code 24 | $ mkdir build 25 | $ cd build 26 | $ cmake .. -G Ninja 27 | @endcode 28 | 29 | Once **CMake** completes, you can use the `install` target to build and install **SPY**. 30 | By default, the library will be installed in the `/usr/local` directory, thus requiring 31 | root privileges. 32 | 33 | @code 34 | $ sudo ninja install 35 | @endcode 36 | 37 | You can select an alternative installation path by specifying the `CMAKE_INSTALL_PREFIX` 38 | option at configuration time. 39 | 40 | @code 41 | $ cmake .. -G Ninja -DCMAKE_INSTALL_PREFIX=path/to/install 42 | $ ninja install 43 | @endcode 44 | 45 | Once installed, **SPY** is usable directly by providing the path to its installed files. 46 | 47 | @section setup-standalone Standalone setup 48 | 49 | You can also use **SPY** via a single standalone file that can be vendored in your own project without 50 | having to deal with **SPY** as a dependency. 51 | 52 | Simply use `wget` to fetch the latest version and place it where you want: 53 | 54 | @code 55 | wget https://raw.githubusercontent.com/jfalcou/spy/refs/heads/standalone/spy.hpp 56 | @endcode 57 | 58 | Use **SPY** by just compiling your code with the include path pointing to the location of this single file. 59 | 60 | @section setup-fetchcontent CMake FetchContent 61 | 62 | You can also use CMake FetchContent operation and use the `spy::spy` library target that our CMake exports. 63 | 64 | @code{cmake} 65 | ##================================================================================================== 66 | ## Your project setup 67 | ##================================================================================================== 68 | cmake_minimum_required(VERSION 3.22) 69 | project(spy-fetch LANGUAGES CXX) 70 | 71 | include(FetchContent) 72 | FetchContent_Declare(spy GIT_REPOSITORY "https://github.com/jfalcou/spy.git") 73 | FetchContent_MakeAvailable(spy) 74 | 75 | add_executable(test_spy ../main.cpp) 76 | target_link_libraries(test_spy PUBLIC spy::spy) 77 | @endcode 78 | 79 | @section setup-cpm Setup with CPM 80 | 81 | The **SPY** library can be setup using [CPM](https://github.com/cpm-cmake/CPM.cmake): 82 | 83 | @code{cmake} 84 | ##================================================================================================== 85 | ## Your project setup 86 | ##================================================================================================== 87 | cmake_minimum_required(VERSION 3.18) 88 | project(spy-cpm LANGUAGES CXX) 89 | 90 | # Setup CPM - See https://github.com/cpm-cmake/CPM.cmake#adding-cpm 91 | include(cpm.cmake) 92 | 93 | CPMAddPackage ( NAME spy 94 | GIT_REPOSITORY "https://github.com/jfalcou/spy.git" 95 | OPTIONS "SPY_BUILD_TEST OFF" 96 | ) 97 | 98 | add_executable(test_spy ../main.cpp) 99 | target_link_libraries(test_spy PUBLIC spy::spy) 100 | @endcode 101 | **/ 102 | //================================================================================================== 103 | -------------------------------------------------------------------------------- /doc/index.hpp: -------------------------------------------------------------------------------- 1 | #error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY 2 | 3 | //================================================================================================== 4 | //! \mainpage The C++ Information Broker 5 | //! 6 | //! Detection and versioning of operating systems, compilers, architecture and other element are 7 | //! traditionally done using preprocessor macros. Library like 8 | //! [Boost.Predef](https://www.boost.org/doc/libs/release/doc/html/predef.html) provides a sanitized 9 | //! interface on top of those but still live in a world where the preprocessor is king. 10 | //! 11 | //! SPY is a C++20 (and onward) library that gathers similar information and provides a `constexpr` 12 | //! compatible interface to access those information, thus making their exploitation within `constexpr` 13 | //! context possible. 14 | //! 15 | //! # Some References 16 | //! 17 | //! - [Our CppCon 2019 Lightning talk slides](https://docs.google.com/presentation/d/1nSBhU4pr5EWznni0MYsyDkMCr3O3q2XS-KQdz2_BRRI/edit?usp=sharing) 18 | //! - [Our CppCon 2019 Lightning talk:](https://www.youtube.com/watch?v=t406o2EhG-A) 19 | //! @htmlonly
@endhtmlonly 20 | //! 21 | //! # A Short Example 22 | //! 23 | //! @code 24 | //! #include 25 | //! #include 26 | //! 27 | //! int main() 28 | //! { 29 | //! std::cout << "OS : " << spy::operating_system << std::endl; 30 | //! std::cout << "CPU Architecture : " << spy::architecture << std::endl; 31 | //! std::cout << "SIMD Instructions : " << spy::simd_instruction_set << std::endl; 32 | //! std::cout << "Compiler : " << spy::compiler << std::endl; 33 | //! std::cout << "libc version : " << spy::libc << std::endl; 34 | //! std::cout << "libstd : " << spy::stdlib << std::endl; 35 | //! } 36 | //! @endcode 37 | //! 38 | //! # Licence 39 | //! 40 | //! This library is licensed under the [Boost Software License](https://opensource.org/licenses/BSL-1.0): 41 | //! 42 | //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 43 | //! Copyright : SPY Project Contributors 44 | //! 45 | //! Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the 46 | //! software and accompanying documentation covered by this license (the "Software") to use, reproduce, 47 | //! display, distribute, execute, and transmit the Software, and to prepare derivative works of the 48 | //! Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the 49 | //! following: 50 | //! 51 | //! The copyright notices in the Software and this entire statement, including the above license grant, 52 | //! this restriction and the following disclaimer, must be included in all copies of the Software, in 53 | //! whole or in part, and all derivative works of the Software, unless such copies or derivative works 54 | //! are solely in the form of machine-executable object code generated by a source language processor. 55 | //! 56 | //! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 57 | //! NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 58 | //! NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE 59 | //! BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING 60 | //! FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 61 | //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 62 | //! 63 | //================================================================================================== 64 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##====================================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##====================================================================================================================== 6 | cmake_minimum_required(VERSION 3.22) 7 | project(spy LANGUAGES CXX) 8 | 9 | ##====================================================================================================================== 10 | option( SPY_BUILD_TEST "Build tests for SPY" ON ) 11 | option( SPY_BUILD_DOCUMENTATION "Build Doxygen for SPY" OFF ) 12 | 13 | ##====================================================================================================================== 14 | include(${PROJECT_SOURCE_DIR}/cmake/dependencies.cmake) 15 | 16 | if(SPY_BUILD_TEST) 17 | include(${PROJECT_SOURCE_DIR}/cmake/compiler.cmake) 18 | endif() 19 | 20 | ##====================================================================================================================== 21 | ## Project setup via copacabana 22 | ##====================================================================================================================== 23 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake ${COPACABANA_SOURCE_DIR}/copacabana/cmake) 24 | include(${COPACABANA_SOURCE_DIR}/copacabana/cmake/copacabana.cmake) 25 | copa_project_version(MAJOR 2 MINOR 0 PATCH 0) 26 | 27 | 28 | ##====================================================================================================================== 29 | ## Summary Display 30 | ##====================================================================================================================== 31 | if(NOT SPY_QUIET) 32 | if(CMAKE_BUILD_TYPE) 33 | message(STATUS "[${PROJECT_NAME}] - Building in ${CMAKE_BUILD_TYPE} mode") 34 | endif() 35 | message(STATUS "[${PROJECT_NAME}] - Unit tests : ${SPY_BUILD_TEST} (via SPY_BUILD_TEST)") 36 | message(STATUS "[${PROJECT_NAME}] - Doxygen : ${SPY_BUILD_DOCUMENTATION} (via SPY_BUILD_DOCUMENTATION)") 37 | set(QUIET_OPTION "") 38 | else() 39 | set(QUIET_OPTION "QUIET") 40 | endif() 41 | 42 | ##====================================================================================================================== 43 | ## Install Process setup 44 | ##====================================================================================================================== 45 | copa_setup_install( LIBRARY spy 46 | FEATURES cxx_std_17 47 | DOC ${PROJECT_SOURCE_DIR}/LICENSE.md 48 | INCLUDE ${PROJECT_SOURCE_DIR}/include/spy 49 | ) 50 | 51 | ##====================================================================================================================== 52 | ## Setup doxygen 53 | ##====================================================================================================================== 54 | if(SPY_BUILD_DOCUMENTATION) 55 | copa_setup_doxygen(${QUIET_OPTION} TARGET spy-doxygen DESTINATION "${PROJECT_BINARY_DIR}/doc") 56 | endif() 57 | 58 | ##====================================================================================================================== 59 | ## Standalone generation 60 | ##====================================================================================================================== 61 | copa_setup_standalone ( QUIET 62 | FILE spy.hpp SOURCE include ROOT spy TARGET spy-standalone 63 | OUTPUT "${PROJECT_BINARY_DIR}" 64 | ) 65 | 66 | ##====================================================================================================================== 67 | ## Tests setup 68 | ##====================================================================================================================== 69 | if(SPY_BUILD_TEST) 70 | enable_testing() 71 | add_custom_target(spy-unit) 72 | add_subdirectory(test) 73 | endif() 74 | -------------------------------------------------------------------------------- /doc/changelog.md: -------------------------------------------------------------------------------- 1 | Change Log {#changelog} 2 | ========== 3 | 4 | # Version 2.0.0 - Denise Bloch 5 | 6 | ## Changelog 7 | 8 | - Features: 9 | - **[BREAKING CHANGE]** Move to C++20 to improve compile times. 10 | - Detect RISC-V and RISC-V SIMD instructions sets. 11 | - Update SIMD detection by upstreaming EVE recent changes. 12 | 13 | - Bugs: 14 | - Fix #55 - Properly detect version for Clang CUDA. 15 | - Use <=> instead of macros for comparisons. 16 | - Fix streaming issues of SPY objects. 17 | 18 | - Infrastructure: 19 | - Update CI to g++ 13 and clang 18. 20 | - Make doxygen generate a spy.tag in the doc files. 21 | - Added a proper clang format settings. 22 | 23 | ## Our SPY: 24 | 25 | [Denise Bloch](https://en.wikipedia.org/wiki/Denise_Bloch) 26 | 27 | # Version 1.1.0 - Julienne Aisner 28 | 29 | ## Changelog 30 | 31 | - Features: 32 | - Split PPC VMX/VSX detection to take PPC ISA into account. 33 | - Separate ARM and ARM SVE tags and add SVE2 detectors. 34 | - Detect and supports sanitizers detection/disabling. 35 | - Implements SVE detection. 36 | - Add detections for ICPX and SYCL. 37 | - Add detections for NVIDIA CUDA usage. 38 | 39 | - Bugs: 40 | - Fix int width for the LLP64 data model by @jmgorius 41 | - Add missing whitespace in stdlib output by @ahoarau 42 | 43 | - Infrastructure: 44 | - Reorganize standalone header location & process. 45 | - Add Emscripten CI targets. 46 | - Now tests and supports Clang-CL. 47 | 48 | ## New Contributors 49 | * @ahoarau made their first contribution in https://github.com/jfalcou/spy/pull/40 50 | * @jmgorius made their first contribution in https://github.com/jfalcou/spy/pull/44 51 | 52 | ## Our SPY: 53 | 54 | [Julienne Aisner](https://en.wikipedia.org/wiki/Julienne_Aisner) 55 | 56 | # Version 1.0.0 - Alix d'Unienville 57 | 58 | ## Changelog 59 | - **BREAKING CHANGES** 60 | - ARM Neon and ASIMD discrimination are in line with SSE-like extensions. `spy::asimd_` is now a descendant of `spy::neon_`. This leads to the removal of `spy::supports_aarch64` 61 | 62 | - Bugs: 63 | - Fix #12 : Remove `` from public headers 64 | 65 | - Infrastructure: 66 | - Fix Circle CI uses a new Docker with more cross-compiler and setup 67 | 68 | ## Our SPY: 69 | 70 | [Alix d'Unienville](https://en.wikipedia.org/wiki/Alix_d%27Unienville) 71 | 72 | # Version 0.0.4 - Eileen Nearne 73 | 74 | ## Changelog 75 | - Infrastructure: 76 | - Fix Circle CI use of compilers and proper dockers 77 | - More strict warnings handling in test 78 | - Bugs: 79 | - No more ALL_CAPS template parameters (Issue #10) 80 | - Fix duplicate macros in AVX512 detection 81 | 82 | ## Our SPY: 83 | 84 | [Eileen Nearne](https://en.wikipedia.org/wiki/Eileen_Nearne) 85 | 86 | # Version 0.0.3 - Virginia Hall 87 | 88 | ## Changelog 89 | - Infrastructure: 90 | - Fixed #5 - SPY now provide a Conan package recipe 91 | - Documentation now uses [Markdeep](https://casual-effects.com/markdeep/) 92 | - Features 93 | - AVX512 detection and sub-ISA detection 94 | - SIMD ISA objects now provide member to access the actual ISA and version number 95 | - Added some macros to help to detect SPY successful detection. This is alas still required for some use cases. 96 | - Added detectors for POSIX 97 | 98 | ## Our SPY: 99 | 100 | [Virginia Hall](https://en.wikipedia.org/wiki/Virginia_Hall) 101 | 102 | # Version 0.0.2 - Blanche Charlet 103 | 104 | ## Changelog 105 | - Support for Continuous Integration 106 | - Fixed #2 - detecting compile-time support for SIMD instructions sets 107 | - Added detectors for data model (LP64, LP32, and all that jazz) 108 | - Added detectors for architecture brand 109 | 110 | ## Our SPY: 111 | 112 | [Blanche Charlet](https://en.wikipedia.org/wiki/Blanche_Charlet) 113 | 114 | # Version 0.0.1 - Peggy Knight 115 | 116 | ## First public release. 117 | 118 | Support for: 119 | - OS vendor 120 | - Compilers version & vendor 121 | - libc version & vendor 122 | - stdlib version & vendor 123 | 124 | ## Our SPY: 125 | [Peggy Knight](https://en.wikipedia.org/wiki/Peggy_Knight) 126 | -------------------------------------------------------------------------------- /test/unit/arch.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | #include 11 | 12 | int main() 13 | { 14 | std::cout << "Check that detected architecture is correct: " << std::endl; 15 | { 16 | #if defined(i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || \ 17 | defined(__i686__) || defined(__i386) || defined(_M_IX86) || defined(_X86_) || \ 18 | defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) 19 | assert( spy::architecture == spy::x86_ ); 20 | assert( !(spy::architecture == spy::amd64_ )); 21 | assert( !(spy::architecture == spy::ppc_ )); 22 | assert( !(spy::architecture == spy::arm_ )); 23 | assert( !(spy::architecture == spy::wasm_ )); 24 | assert( !(spy::architecture == spy::riscv_ )); 25 | #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__amd64) || defined(_M_X64) 26 | assert( !(spy::architecture == spy::x86_ )); 27 | assert( spy::architecture == spy::amd64_ ); 28 | assert( !(spy::architecture == spy::ppc_ )); 29 | assert( !(spy::architecture == spy::arm_ )); 30 | assert( !(spy::architecture == spy::wasm_ )); 31 | assert( !(spy::architecture == spy::riscv_ )); 32 | #elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || \ 33 | defined(_M_PPC) || defined(_ARCH_PPC) || defined(__PPCGECKO__) || defined(__PPCBROADWAY__) || \ 34 | defined(_XENON) 35 | assert( !(spy::architecture == spy::x86_ )); 36 | assert( !(spy::architecture == spy::amd64_ )); 37 | assert( spy::architecture == spy::ppc_ ); 38 | assert( !(spy::architecture == spy::arm_ )); 39 | assert( !(spy::architecture == spy::wasm_ )); 40 | assert( !(spy::architecture == spy::riscv_ )); 41 | #elif defined(__arm__) || defined(__arm64) || defined(__thumb__) || defined(__TARGET_ARCH_ARM) || \ 42 | defined(__TARGET_ARCH_THUMB) || defined(_M_ARM) || defined(__ARM_ARCH_ISA_A64) 43 | assert( !(spy::architecture == spy::x86_) ); 44 | assert( !(spy::architecture == spy::amd64_) ); 45 | assert( !(spy::architecture == spy::ppc_) ); 46 | assert( spy::architecture == spy::arm_ ); 47 | assert( !(spy::architecture == spy::wasm_) ); 48 | assert( !(spy::architecture == spy::riscv_ )); 49 | #elif defined(__wasm__) 50 | assert( !(spy::architecture == spy::x86_ )); 51 | assert( !(spy::architecture == spy::amd64_ )); 52 | assert( !(spy::architecture == spy::ppc_ )); 53 | assert( !(spy::architecture == spy::arm_ )); 54 | assert( spy::architecture == spy::wasm_ ); 55 | assert( !(spy::architecture == spy::riscv_ )); 56 | #elif defined(__riscv) 57 | assert( !(spy::architecture == spy::x86_ )); 58 | assert( !(spy::architecture == spy::amd64_ )); 59 | assert( !(spy::architecture == spy::ppc_ )); 60 | assert( !(spy::architecture == spy::arm_ )); 61 | assert( !(spy::architecture == spy::wasm_ )); 62 | assert( spy::architecture == spy::riscv_ ); 63 | #else 64 | assert( !(spy::architecture == spy::x86_ )); 65 | assert( !(spy::architecture == spy::amd64_ )); 66 | assert( !(spy::architecture == spy::ppc_ )); 67 | assert( !(spy::architecture == spy::arm_ )); 68 | assert( !(spy::architecture == spy::wasm_ )); 69 | assert( !(spy::architecture == spy::riscv_ )); 70 | #endif 71 | 72 | std::cout << "X86 status: " << std::boolalpha << (spy::architecture == spy::x86_ ) << std::endl; 73 | std::cout << "AMD64 status: " << std::boolalpha << (spy::architecture == spy::amd64_) << std::endl; 74 | std::cout << "PPC status: " << std::boolalpha << (spy::architecture == spy::ppc_ ) << std::endl; 75 | std::cout << "ARM status: " << std::boolalpha << (spy::architecture == spy::arm_ ) << std::endl; 76 | std::cout << "WASM status: " << std::boolalpha << (spy::architecture == spy::wasm_ ) << std::endl; 77 | std::cout << "RISC-V status: " << std::boolalpha << (spy::architecture == spy::riscv_) << std::endl; 78 | } 79 | std::cout << "Done." << std::endl; 80 | } 81 | -------------------------------------------------------------------------------- /doc/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | $projectname: $title 10 | $title 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | $treeview 28 | $search 29 | $mathjax 30 | 31 | $extrastylesheet 32 | 33 | 34 | 35 | 36 |
37 | 38 | 39 | 40 | 42 | 43 |
44 | 45 | 46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
55 |
$projectname $projectnumber 56 |
57 |
$projectbrief
58 |
63 |
$projectbrief
64 |
$searchbox
76 |
77 | 78 | 79 | -------------------------------------------------------------------------------- /test/unit/os.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | #include 11 | 12 | int main() 13 | { 14 | std::cout << "Check that detected OS is correct: " << std::flush; 15 | { 16 | #if defined(__ANDROID__) 17 | assert( spy::operating_system == spy::android_ ); 18 | assert( !(spy::operating_system == spy::bsd_ )); 19 | assert( !(spy::operating_system == spy::cygwin_)); 20 | assert( !(spy::operating_system == spy::ios_ )); 21 | assert( !(spy::operating_system == spy::linux_ )); 22 | assert( !(spy::operating_system == spy::macos_ )); 23 | assert( !(spy::operating_system == spy::unix_ )); 24 | assert( !(spy::operating_system == spy::windows_)); 25 | #elif defined(BSD) || defined(_SYSTYPE_BSD) 26 | assert( !(spy::operating_system == spy::android_)); 27 | assert( spy::operating_system == spy::bsd_ ); 28 | assert( !(spy::operating_system == spy::cygwin_)); 29 | assert( !(spy::operating_system == spy::ios_ )); 30 | assert( !(spy::operating_system == spy::linux_ )); 31 | assert( !(spy::operating_system == spy::macos_ )); 32 | assert( !(spy::operating_system == spy::unix_ )); 33 | assert( !(spy::operating_system == spy::windows_)); 34 | #elif defined(__CYGWIN__) 35 | assert( !(spy::operating_system == spy::android_)); 36 | assert( !(spy::operating_system == spy::bsd_ )); 37 | assert( spy::operating_system == spy::cygwin_ ); 38 | assert( !(spy::operating_system == spy::ios_ )); 39 | assert( !(spy::operating_system == spy::linux_ )); 40 | assert( !(spy::operating_system == spy::macos_ )); 41 | assert( !(spy::operating_system == spy::unix_ )); 42 | assert( !(spy::operating_system == spy::windows_)); 43 | #elif defined(__APPLE__) && defined(__MACH__) && defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) 44 | assert( !(spy::operating_system == spy::android_)); 45 | assert( !(spy::operating_system == spy::bsd_ )); 46 | assert( !(spy::operating_system == spy::cygwin_)); 47 | assert( spy::operating_system == spy::ios_ ); 48 | assert( !(spy::operating_system == spy::linux_ )); 49 | assert( !(spy::operating_system == spy::macos_ )); 50 | assert( !(spy::operating_system == spy::unix_ )); 51 | assert( !(spy::operating_system == spy::windows_)); 52 | #elif defined(linux) || defined(__linux) 53 | assert( !(spy::operating_system == spy::android_)); 54 | assert( !(spy::operating_system == spy::bsd_ )); 55 | assert( !(spy::operating_system == spy::cygwin_)); 56 | assert( !(spy::operating_system == spy::ios_ )); 57 | assert( spy::operating_system == spy::linux_ ); 58 | assert( !(spy::operating_system == spy::macos_ )); 59 | assert( !(spy::operating_system == spy::unix_ )); 60 | assert( !(spy::operating_system == spy::windows_)); 61 | #elif defined(macintosh) || defined(Macintosh) || (defined(__APPLE__) && defined(__MACH__)) 62 | assert( !(spy::operating_system == spy::android_)); 63 | assert( !(spy::operating_system == spy::bsd_ )); 64 | assert( !(spy::operating_system == spy::cygwin_)); 65 | assert( !(spy::operating_system == spy::ios_ )); 66 | assert( !(spy::operating_system == spy::linux_ )); 67 | assert( spy::operating_system == spy::macos_ ); 68 | assert( !(spy::operating_system == spy::unix_ )); 69 | assert( !(spy::operating_system == spy::windows_)); 70 | #elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) 71 | assert( !(spy::operating_system == spy::android_)); 72 | assert( !(spy::operating_system == spy::bsd_ )); 73 | assert( !(spy::operating_system == spy::cygwin_)); 74 | assert( !(spy::operating_system == spy::ios_ )); 75 | assert( !(spy::operating_system == spy::linux_ )); 76 | assert( !(spy::operating_system == spy::macos_ )); 77 | assert( spy::operating_system == spy::unix_ ); 78 | assert( !(spy::operating_system == spy::windows_)); 79 | #elif defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) 80 | assert( !(spy::operating_system == spy::android_)); 81 | assert( !(spy::operating_system == spy::bsd_ )); 82 | assert( !(spy::operating_system == spy::cygwin_)); 83 | assert( !(spy::operating_system == spy::ios_ )); 84 | assert( !(spy::operating_system == spy::linux_ )); 85 | assert( !(spy::operating_system == spy::macos_ )); 86 | assert( !(spy::operating_system == spy::unix_ )); 87 | assert( spy::operating_system == spy::windows_ ); 88 | #endif 89 | } 90 | std::cout << "Done." << std::endl; 91 | std::cout << "Detected OS: " << spy::operating_system << std::endl; 92 | } 93 | -------------------------------------------------------------------------------- /include/spy/stdlib.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | // Make sure the proper header is included to detect libstd 11 | #include 12 | 13 | #include 14 | 15 | namespace spy::_ 16 | { 17 | enum class stdlib 18 | { 19 | undefined_ = -1, 20 | libcpp_, 21 | gnucpp_ 22 | }; 23 | 24 | template struct stdlib_info 25 | { 26 | static constexpr stdlib vendor = Lib; 27 | static constexpr version_id version = {}; 28 | 29 | inline constexpr explicit operator bool() const noexcept; 30 | 31 | template constexpr bool operator==(stdlib_info const&) const noexcept 32 | { 33 | return C2 == vendor; 34 | } 35 | 36 | template 37 | constexpr bool operator==(stdlib_info const& c2) const noexcept 38 | { 39 | return C2 == vendor && version == c2.version; 40 | } 41 | 42 | template 43 | constexpr std::partial_ordering operator<=>(stdlib_info const& c2) const noexcept 44 | { 45 | if constexpr (vendor == C2) return version <=> c2.version; 46 | else return std::partial_ordering::unordered; 47 | } 48 | }; 49 | 50 | template<_::stream OS, stdlib SLib, int M, int N, int P> auto& operator<<(OS& os, stdlib_info const& p) 51 | { 52 | if (SLib == stdlib::libcpp_) return os << "libc++ Standard C++ Library " << p.version; 53 | if (SLib == stdlib::gnucpp_) return os << "GNU Standard C++ Library " << p.version; 54 | 55 | return os << "Undefined Standard C++ Library"; 56 | } 57 | 58 | template using libcpp_t = stdlib_info; 59 | template using gnucpp_t = stdlib_info; 60 | } 61 | 62 | namespace spy 63 | { 64 | #if defined(_LIBCPP_VERSION) 65 | #define SPY_STDLIB_IS_LIBCPP 66 | using stdlib_type = _::libcpp_t<(_LIBCPP_VERSION / 1000) % 10, 0, _LIBCPP_VERSION % 1000>; 67 | #elif defined(__GLIBCXX__) 68 | #define SPY_STDLIB_IS_GLIBCXX 69 | #define SPY0 (__GLIBCXX__ / 100) 70 | using stdlib_type = _::gnucpp_t<(SPY0 / 100) % 10000, SPY0 % 100, __GLIBCXX__ % 100>; 71 | #undef SPY0 72 | #else 73 | #define SPY_STDLIB_IS_UNKNOWN 74 | using stdlib_type = _::stdlib_info<_::stdlib::undefined_, -1, 0, 0>; 75 | #endif 76 | 77 | //================================================================================================ 78 | //! @ingroup api 79 | //! @brief C++ Standard Library version reporting value 80 | //! 81 | //! The `spy::stdlib` object can be compared to any other stdlib related value to verify 82 | //! if the code being compiled with a specific version of the C++ standard library. 83 | //! 84 | //! Any stdlib related value can be checked for equality or ordering for a given version. The targeted 85 | //! version is then specified using a stdlib-dependent literal. 86 | //! 87 | //! Additionally, any of the stdlib related value are convertible to `bool`. They evaluates to `true` if they 88 | //! matches the correct standard library currently used. 89 | //! 90 | //! @groupheader{Supported Value} 91 | //! 92 | //! Name | Vendor 93 | //! ----------------- | ------------- 94 | //! `spy::libcpp_` | Clang libcpp 95 | //! `spy::gnucpp_` | GNU C++ standard library 96 | //! 97 | //! @groupheader{Example} 98 | //! @godbolt{samples/stdlib.cpp} 99 | //================================================================================================ 100 | constexpr inline auto stdlib = stdlib_type{}; 101 | } 102 | 103 | namespace spy::_ 104 | { 105 | template inline constexpr stdlib_info::operator bool() const noexcept 106 | { 107 | return spy::stdlib == *this; 108 | } 109 | } 110 | 111 | namespace spy 112 | { 113 | //================================================================================================ 114 | // STDLIBs detector stand-alone instances 115 | //================================================================================================ 116 | constexpr inline auto libcpp_ = _::libcpp_t<-1, 0, 0>{}; 117 | constexpr inline auto gnucpp_ = _::gnucpp_t<-1, 0, 0>{}; 118 | } 119 | 120 | namespace spy::literal 121 | { 122 | template constexpr auto operator""_libcpp() 123 | { 124 | return _::literal_wrap<_::libcpp_t, c...>(); 125 | } 126 | 127 | template constexpr auto operator""_gnucpp() 128 | { 129 | return _::literal_wrap<_::gnucpp_t, c...>(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /include/spy/arch.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | namespace spy::_ 11 | { 12 | enum class archs 13 | { 14 | undefined_ = -1, 15 | x86_ = 10, 16 | amd64_ = 11, 17 | ppc_ = 20, 18 | arm_ = 30, 19 | wasm_ = 40, 20 | riscv_ = 50 21 | }; 22 | 23 | template struct arch_info 24 | { 25 | static constexpr archs vendor = Arch; 26 | 27 | inline constexpr explicit operator bool() const noexcept; 28 | 29 | template constexpr bool operator==(arch_info const&) const noexcept { return A2 == vendor; } 30 | 31 | template<_::stream OS> friend auto& operator<<(OS& os, arch_info const&) 32 | { 33 | if (Arch == archs::x86_) return os << "X86"; 34 | if (Arch == archs::amd64_) return os << "AMD64"; 35 | if (Arch == archs::ppc_) return os << "PowerPC"; 36 | if (Arch == archs::arm_) return os << "ARM"; 37 | if (Arch == archs::wasm_) return os << "WebAssembly"; 38 | if (Arch == archs::riscv_) return os << "RISC-V"; 39 | 40 | return os << "Undefined Architecture"; 41 | } 42 | }; 43 | } 44 | 45 | namespace spy 46 | { 47 | #if defined(i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || \ 48 | defined(__i386) || defined(_M_IX86) || defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \ 49 | defined(__INTEL__) 50 | using arch_type = _::arch_info<_::archs::x86_>; 51 | #define SPY_ARCH_IS_X86 52 | #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__amd64) || defined(_M_X64) 53 | #define SPY_ARCH_IS_AMD64 54 | using arch_type = _::arch_info<_::archs::amd64_>; 55 | #elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(_M_PPC) || \ 56 | defined(_ARCH_PPC) || defined(__PPCGECKO__) || defined(__PPCBROADWAY__) || defined(_XENON) 57 | using arch_type = _::arch_info<_::archs::ppc_>; 58 | #define SPY_ARCH_IS_PPC 59 | #elif defined(__arm__) || defined(__arm64) || defined(__thumb__) || defined(__TARGET_ARCH_ARM) || \ 60 | defined(__TARGET_ARCH_THUMB) || defined(_M_ARM) || defined(__ARM_ARCH_ISA_A64) 61 | using arch_type = _::arch_info<_::archs::arm_>; 62 | #define SPY_ARCH_IS_ARM 63 | #elif defined(__wasm__) 64 | using arch_type = _::arch_info<_::archs::wasm_>; 65 | #define SPY_ARCH_IS_WASM 66 | #elif defined(__riscv) 67 | using arch_type = _::arch_info<_::archs::riscv_>; 68 | #define SPY_ARCH_IS_RISCV 69 | #else 70 | #define SPY_ARCH_IS_UNKNOWN 71 | using arch_type = _::arch_info<_::archs::undefined_>; 72 | #endif 73 | 74 | //================================================================================================ 75 | //! @ingroup api 76 | //! @brief Architecture reporting value 77 | //! 78 | //! The `spy::architecture` object can be compared to any other architecture related value to verify 79 | //! if the code being compiled is compiled for a given CPU architecture. 80 | //! 81 | //! Additionally, any of the architecture related value are convertible to `bool`. They evaluates to `true` if they 82 | //! matches the correct architecture currently targeted. 83 | //! 84 | //! @groupheader{Supported Value} 85 | //! 86 | //! Name | Architecture 87 | //! --------------- | ------------- 88 | //! `spy::amd64` | Intel X86-64 and similar architectures. 89 | //! `spy::arm` | ARM. 90 | //! `spy::ppc` | PowerPC. 91 | //! `spy::riscv` | RISC-V. 92 | //! `spy::wasm` | WASM pseudo-architecture. 93 | //! `spy::x86` | Intel X86. 94 | //! 95 | //! @groupheader{Example} 96 | //! @godbolt{samples/architecture.cpp} 97 | //================================================================================================ 98 | constexpr inline arch_type architecture; 99 | } 100 | 101 | namespace spy::_ 102 | { 103 | template inline constexpr arch_info::operator bool() const noexcept 104 | { 105 | return spy::architecture == *this; 106 | } 107 | } 108 | 109 | namespace spy 110 | { 111 | //================================================================================================ 112 | // Architecture detector stand-alone instances 113 | //================================================================================================ 114 | constexpr inline auto x86_ = _::arch_info<_::archs::x86_>{}; 115 | constexpr inline auto amd64_ = _::arch_info<_::archs::amd64_>{}; 116 | constexpr inline auto ppc_ = _::arch_info<_::archs::ppc_>{}; 117 | constexpr inline auto arm_ = _::arch_info<_::archs::arm_>{}; 118 | constexpr inline auto wasm_ = _::arch_info<_::archs::wasm_>{}; 119 | constexpr inline auto riscv_ = _::arch_info<_::archs::riscv_>{}; 120 | } 121 | -------------------------------------------------------------------------------- /include/spy/os.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | #if defined(__APPLE__) || defined(__APPLE_CC__) || defined(macintosh) 11 | #include 12 | #endif 13 | 14 | namespace spy::_ 15 | { 16 | enum class systems 17 | { 18 | undefined_ = -1, 19 | android_, 20 | bsd_, 21 | cygwin_, 22 | ios_, 23 | linux_, 24 | macos_, 25 | unix_, 26 | windows_ 27 | }; 28 | 29 | template struct os_info 30 | { 31 | static constexpr systems vendor = OpSys; 32 | 33 | inline constexpr explicit operator bool() const noexcept; 34 | 35 | template constexpr bool operator==(os_info const&) const noexcept { return C2 == vendor; } 36 | }; 37 | 38 | template<_::stream OS, systems OpSys> auto& operator<<(OS& os, os_info const&) 39 | { 40 | if (OpSys == systems::android_) return os << "Android"; 41 | if (OpSys == systems::bsd_) return os << "BSD"; 42 | if (OpSys == systems::cygwin_) return os << "Cygwin"; 43 | if (OpSys == systems::ios_) return os << "iOs"; 44 | if (OpSys == systems::linux_) return os << "Linux"; 45 | if (OpSys == systems::macos_) return os << "MacOs"; 46 | if (OpSys == systems::unix_) return os << "UNIX"; 47 | if (OpSys == systems::windows_) return os << "Windows"; 48 | 49 | return os << "Undefined Operating System"; 50 | } 51 | } 52 | 53 | namespace spy 54 | { 55 | #if defined(__ANDROID__) 56 | #define SPY_OS_IS_ANDROID 57 | using os_type = _::os_info<_::systems::android_>; 58 | #elif defined(BSD) || defined(_SYSTYPE_BSD) 59 | #define SPY_OS_IS_BSD 60 | using os_type = _::os_info<_::systems::bsd_>; 61 | #elif defined(__CYGWIN__) 62 | #define SPY_OS_IS_CYGWIN 63 | using os_type = _::os_info<_::systems::cygwin_>; 64 | #elif defined(__APPLE__) && defined(__MACH__) && defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) 65 | #define SPY_OS_IS_IOS 66 | using os_type = _::os_info<_::systems::ios_>; 67 | #elif defined(linux) || defined(__linux) 68 | #define SPY_OS_IS_LINUX 69 | using os_type = _::os_info<_::systems::linux_>; 70 | #elif defined(macintosh) || defined(Macintosh) || (defined(__APPLE__) && defined(__MACH__)) 71 | #define SPY_OS_IS_MACOS 72 | using os_type = _::os_info<_::systems::macos_>; 73 | #elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) 74 | #define SPY_OS_IS_UNIX 75 | using os_type = _::os_info<_::systems::unix_>; 76 | #elif defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) 77 | #define SPY_OS_IS_WINDOWS 78 | using os_type = _::os_info<_::systems::windows_>; 79 | #else 80 | #define SPY_OS_IS_UNKNOWN 81 | using os_type = _::os_info<_::systems::undefined_>; 82 | #endif 83 | 84 | //================================================================================================ 85 | //! @ingroup api 86 | //! @brief OS reporting value 87 | //! 88 | //! The `spy::operating_system` object can be compared to any other OS related value to verify 89 | //! if the code being compiled is compiled on a given Operating Systems. 90 | //! 91 | //! Additionally, any of the OS related value are convertible to `bool`. They evaluates to `true` if they 92 | //! matches the correct OS currently used. 93 | //! 94 | //! @groupheader{Supported Value} 95 | //! 96 | //! Name | Operating System 97 | //! --------------- | ------------- 98 | //! `spy::android_` | Android 99 | //! `spy::bsd` | BSD 100 | //! `spy::cygwin_` | CYGWIN 101 | //! `spy::ios_` | iOS 102 | //! `spy::linux_` | Linux 103 | //! `spy::macos_` | MacOS 104 | //! `spy::unix_` | UNIX 105 | //! `spy::windows_` | Windows 106 | //! 107 | //! @groupheader{Example} 108 | //! @godbolt{samples/os.cpp} 109 | //================================================================================================ 110 | constexpr inline os_type operating_system; 111 | } 112 | 113 | namespace spy::_ 114 | { 115 | template inline constexpr os_info::operator bool() const noexcept 116 | { 117 | return spy::operating_system == *this; 118 | } 119 | } 120 | 121 | namespace spy 122 | { 123 | constexpr inline auto android_ = _::os_info<_::systems::android_>{}; 124 | constexpr inline auto bsd_ = _::os_info<_::systems::bsd_>{}; 125 | constexpr inline auto cygwin_ = _::os_info<_::systems::cygwin_>{}; 126 | constexpr inline auto ios_ = _::os_info<_::systems::ios_>{}; 127 | constexpr inline auto linux_ = _::os_info<_::systems::linux_>{}; 128 | constexpr inline auto macos_ = _::os_info<_::systems::macos_>{}; 129 | constexpr inline auto unix_ = _::os_info<_::systems::unix_>{}; 130 | constexpr inline auto windows_ = _::os_info<_::systems::windows_>{}; 131 | } 132 | 133 | namespace spy::supports 134 | { 135 | #if defined(SPY_DOXYGEN_INVOKED) 136 | //================================================================================================ 137 | //! @ingroup api 138 | //! @brief POSIX supports indicator. 139 | //! 140 | //! Evaluates to `true` if current OS supports POSIX system calls and functions. 141 | //! 142 | //! @groupheader{Example} 143 | //! @godbolt{samples/posix.cpp} 144 | //================================================================================================ 145 | constexpr inline auto posix_ = **implementation specified * *; 146 | #else 147 | #if (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) || (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600) 148 | #define SPY_SUPPORTS_POSIX 149 | constexpr inline auto posix_ = true; 150 | #else 151 | constexpr inline auto posix_ = false; 152 | #endif 153 | #endif 154 | } 155 | -------------------------------------------------------------------------------- /doc/layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /include/spy/libc.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | // Make sure the proper header is included to detect GNU libc 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | namespace spy::_ 17 | { 18 | enum class libC 19 | { 20 | undefined_ = -1, 21 | cloudabi_, 22 | uc_, 23 | vms_, 24 | zos_, 25 | gnu_ 26 | }; 27 | 28 | template struct libc_info 29 | { 30 | static constexpr libC vendor = Lib; 31 | static constexpr version_id version = {}; 32 | 33 | inline constexpr explicit operator bool() const noexcept; 34 | 35 | template constexpr bool operator==(libc_info const&) const noexcept { return C2 == vendor; } 36 | 37 | template 38 | constexpr bool operator==(libc_info const& c2) const noexcept 39 | { 40 | return C2 == vendor && version == c2.version; 41 | } 42 | 43 | template 44 | constexpr auto operator<=>(libc_info const& c2) const noexcept 45 | { 46 | if constexpr (vendor == C2) return version <=> c2.version; 47 | else return vendor <=> C2; 48 | } 49 | }; 50 | 51 | template<_::stream OS, libC C, int M, int N, int P> auto& operator<<(OS& os, libc_info const& c) 52 | { 53 | if (c.vendor == libC::cloudabi_) return os << "CloudABI Standard C Library " << c.version; 54 | if (c.vendor == libC::uc_) return os << "uClibc Standard C Library " << c.version; 55 | if (c.vendor == libC::vms_) return os << "VMS Standard C Library " << c.version; 56 | if (c.vendor == libC::zos_) return os << "z/OS Standard C Library " << c.version; 57 | if (c.vendor == libC::gnu_) return os << "GNU Standard C Library " << c.version; 58 | 59 | return os << "Undefined Standard C Library"; 60 | } 61 | 62 | template using cloudabi_t = libc_info; 63 | template using uc_t = libc_info; 64 | template using vms_t = libc_info; 65 | template using zos_t = libc_info; 66 | template using gnu_t = libc_info; 67 | } 68 | 69 | namespace spy 70 | { 71 | //================================================================================================ 72 | // LIBC detection object type 73 | //================================================================================================ 74 | #if defined(__cloudlibc__) 75 | #define SPY_LIBC_IS_CLOUDABI 76 | using libc_type = _::cloudabi_t<__cloudlibc_major__, __cloudlibc_minor__, 0>; 77 | #elif defined(__GLIBC__) 78 | #define SPY_LIBC_IS_GNU 79 | using libc_type = _::gnu_t<__GLIBC__, __GLIBC_MINOR__, 0>; 80 | #elif defined(__GNU_LIBRARY__) 81 | #define SPY_LIBC_IS_GNU 82 | using libc_type = _::gnu_t<__GNU_LIBRARY__, __GNU_LIBRARY_MINOR__, 0>; 83 | #elif defined(__UCLIBC__) 84 | #define SPY_LIBC_IS_UCLIBC 85 | using libc_type = _::uc_t<__UCLIBC_MAJOR__, __UCLIBC_MINOR__, __UCLIBC_SUBLEVEL__>; 86 | #elif defined(__CRTL_VER) 87 | #define SPY_LIBC_IS_VMS 88 | #define SPY0 (__CRTL_VER / 100) 89 | using libc_type = _::vms_t<(SPY0 / 100000) % 100, (SPY0 / 1000) % 100, (SPY0) % 100>; 90 | #undef SPY0 91 | #elif defined(__LIBREL__) 92 | #define SPY_LIBC_IS_ZOS 93 | using libc_type = _::zos_t < (__LIBREL__ & 0xF000000) >> 24, (__LIBREL__ & 0xFF0000) >> 16, (__LIBREL__ & 0xFFFF) > ; 94 | #else 95 | #define SPY_LIBC_IS_UNKNOWN 96 | using libc_type = _::libc_info<_::libC::undefined_, -1, 0, 0>; 97 | #endif 98 | 99 | //================================================================================================ 100 | //! @ingroup api 101 | //! @brief LIBC version reporting value 102 | //! 103 | //! The `spy::libc` object can be compared to any other libc related value to verify 104 | //! if the code being compiled with a specific version of the libc. 105 | //! 106 | //! Any libc related value can be checked for equality or ordering for a given version. The targeted 107 | //! version is then specified using a libc-dependent literal. 108 | //! 109 | //! Additionally, any of the libc related value are convertible to `bool`. They evaluates to `true` if they 110 | //! matches the correct libc currently used. 111 | //! 112 | //! @groupheader{Supported Value} 113 | //! 114 | //! Name | Vendor 115 | //! ----------------- | ------------- 116 | //! `spy::cloudabi_` | CloudABI 117 | //! `spy::uc_` | uClibc 118 | //! `spy::vms_` | VMS 119 | //! `spy::zos_` | zOS 120 | //! `spy::gnu_` | GNU 121 | //! 122 | //! @groupheader{Example} 123 | //! @godbolt{samples/libc.cpp} 124 | //================================================================================================ 125 | constexpr inline auto libc = libc_type{}; 126 | } 127 | 128 | namespace spy::_ 129 | { 130 | template inline constexpr libc_info::operator bool() const noexcept 131 | { 132 | return spy::libc == *this; 133 | } 134 | } 135 | 136 | namespace spy 137 | { 138 | //================================================================================================ 139 | // LIBCs detector stand-alone instances 140 | //================================================================================================ 141 | constexpr inline auto cloudabi_ = _::cloudabi_t<-1, 0, 0>{}; 142 | constexpr inline auto uc_ = _::uc_t<-1, 0, 0>{}; 143 | constexpr inline auto vms_ = _::vms_t<-1, 0, 0>{}; 144 | constexpr inline auto zos_ = _::zos_t<-1, 0, 0>{}; 145 | constexpr inline auto gnu_ = _::gnu_t<-1, 0, 0>{}; 146 | } 147 | 148 | namespace spy::literal 149 | { 150 | //! @ingroup api 151 | //! @brief User-defined suffix for the CloudABI libc version definition 152 | template constexpr auto operator""_cloud() 153 | { 154 | return _::literal_wrap<_::cloudabi_t, c...>(); 155 | } 156 | 157 | //! @ingroup api 158 | //! @brief User-defined suffix for the uClibc version definition 159 | template constexpr auto operator""_uc() 160 | { 161 | return _::literal_wrap<_::uc_t, c...>(); 162 | } 163 | 164 | //! @ingroup api 165 | //! @brief User-defined suffix for the VMS libc version definition 166 | template constexpr auto operator""_vms() 167 | { 168 | return _::literal_wrap<_::vms_t, c...>(); 169 | } 170 | 171 | //! @ingroup api 172 | //! @brief User-defined suffix for the zOS libc version definition 173 | template constexpr auto operator""_zos() 174 | { 175 | return _::literal_wrap<_::zos_t, c...>(); 176 | } 177 | 178 | //! @ingroup api 179 | //! @brief User-defined suffix for the GNU libc version definition 180 | template constexpr auto operator""_gnu() 181 | { 182 | return _::literal_wrap<_::gnu_t, c...>(); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /include/spy/simd/x86.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | #if !defined(SPY_SIMD_DETECTED) && defined(__AVX512F__) 10 | #define SPY_SIMD_IS_X86_AVX512 11 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::avx512_ 12 | 13 | #if defined(__AVX512BW__) 14 | #define SPY_SIMD_IS_X86_AVX512_BW 15 | #endif 16 | 17 | #if defined(__AVX512CD__) 18 | #define SPY_SIMD_IS_X86_AVX512_CD 19 | #endif 20 | 21 | #if defined(__AVX512DQ__) 22 | #define SPY_SIMD_IS_X86_AVX512_DQ 23 | #endif 24 | 25 | #if defined(__AVX512ER__) 26 | #define SPY_SIMD_IS_X86_AVX512_ER 27 | #endif 28 | 29 | #if defined(__AVX512IFMA__) 30 | #define SPY_SIMD_IS_X86_AVX512_IFMA 31 | #endif 32 | 33 | #if defined(__AVX512PF__) 34 | #define SPY_SIMD_IS_X86_AVX512_PF 35 | #endif 36 | 37 | #if defined(__AVX512VL__) 38 | #define SPY_SIMD_IS_X86_AVX512_VL 39 | #endif 40 | 41 | #if defined(__AVX512VPOPCNTDQ__) 42 | #define SPY_SIMD_IS_X86_AVX512_POPCNTDQ 43 | #endif 44 | 45 | #if defined(__AVX5124FMAPS__) 46 | #define SPY_SIMD_IS_X86_AVX512_4FMAPS 47 | #endif 48 | 49 | #if defined(__AVX5124VNNIW__) 50 | #define SPY_SIMD_IS_X86_AVX512_VNNIW 51 | #endif 52 | 53 | #if defined(__AVX512VBMI__) 54 | #define SPY_SIMD_IS_X86_AVX512_VBMI 55 | #endif 56 | 57 | #if defined(__AVX512BF16__) 58 | #define SPY_SIMD_IS_X86_AVX512_BF16 59 | #endif 60 | 61 | #if defined(__AVX512BITALG__) 62 | #define SPY_SIMD_IS_X86_AVX512_BITALG 63 | #endif 64 | 65 | #if defined(__AVX512VBMI2__) 66 | #define SPY_SIMD_IS_X86_AVX512_VBMI2 67 | #endif 68 | 69 | #if defined(__AVX512VNNI__) 70 | #define SPY_SIMD_IS_X86_AVX512_VNNI 71 | #endif 72 | 73 | #if defined(__AVX512VP2INTERSECT__) 74 | #define SPY_SIMD_IS_X86_AVX512_VP2INTERSECT 75 | #endif 76 | 77 | #endif 78 | 79 | #if !defined(SPY_SIMD_DETECTED) && defined(__AVX2__) 80 | #define SPY_SIMD_IS_X86_AVX2 81 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::avx2_ 82 | #endif 83 | 84 | #if !defined(SPY_SIMD_DETECTED) && defined(__AVX__) 85 | #define SPY_SIMD_IS_X86_AVX 86 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::avx_ 87 | #endif 88 | 89 | #if !defined(SPY_SIMD_DETECTED) && defined(__SSE4_2__) 90 | #define SPY_SIMD_IS_X86_SSE4_2 91 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::sse42_ 92 | #endif 93 | 94 | #if !defined(SPY_SIMD_DETECTED) && defined(__SSE4_1__) 95 | #define SPY_SIMD_IS_X86_SSE4_1 96 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::sse41_ 97 | #endif 98 | 99 | #if !defined(SPY_SIMD_DETECTED) && defined(__SSSE3__) 100 | #define SPY_SIMD_IS_X86_SSSE3 101 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::ssse3_ 102 | #endif 103 | 104 | #if !defined(SPY_SIMD_DETECTED) && defined(__SSE3__) 105 | #define SPY_SIMD_IS_X86_SSE3 106 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::sse3_ 107 | #endif 108 | 109 | #if !defined(SPY_SIMD_DETECTED) && (defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)) 110 | #define SPY_SIMD_IS_X86_SSE2 111 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::sse2_ 112 | #endif 113 | 114 | #if !defined(SPY_SIMD_DETECTED) && (defined(__SSE__) || defined(_M_IX86_FP)) 115 | #define SPY_SIMD_IS_X86_SSE 116 | #define SPY_SIMD_DETECTED ::spy::_::simd_version::sse1_ 117 | #endif 118 | 119 | #if defined(SPY_SIMD_DETECTED) && !defined(SPY_SIMD_VENDOR) 120 | #define SPY_SIMD_IS_X86 121 | #define SPY_SIMD_VENDOR ::spy::_::simd_isa::x86_ 122 | #endif 123 | 124 | namespace spy::supports 125 | { 126 | //================================================================================================ 127 | // Supplemental ISA 128 | //================================================================================================ 129 | #if defined(__FMA__) 130 | #define SPY_SIMD_SUPPORTS_FMA 131 | constexpr inline auto fma_ = true; 132 | #else 133 | constexpr inline auto fma_ = false; 134 | #endif 135 | 136 | #if defined(__FMA4__) 137 | #define SPY_SIMD_SUPPORTS_FMA4 138 | constexpr inline auto fma4_ = true; 139 | #else 140 | constexpr inline auto fma4_ = false; 141 | #endif 142 | 143 | #if defined(__XOP__) 144 | #define SPY_SIMD_SUPPORTS_XOP 145 | constexpr inline auto xop_ = true; 146 | #else 147 | constexpr inline auto xop_ = false; 148 | #endif 149 | 150 | #if defined(__F16C__) 151 | #define SPY_SIMD_SUPPORTS_F16C 152 | constexpr inline auto f16c_ = true; 153 | #else 154 | constexpr inline auto f16c_ = false; 155 | #endif 156 | 157 | namespace avx512 158 | { 159 | #if defined(__AVX512BW__) 160 | #define SPY_SIMD_IS_X86_AVX512_BW 161 | constexpr inline auto bw_ = true; 162 | #else 163 | constexpr inline auto bw_ = false; 164 | #endif 165 | 166 | #if defined(__AVX512CD__) 167 | #define SPY_SIMD_IS_X86_AVX512_CD 168 | constexpr inline auto cd_ = true; 169 | #else 170 | constexpr inline auto cd_ = false; 171 | #endif 172 | 173 | #if defined(__AVX512DQ__) 174 | #define SPY_SIMD_IS_X86_AVX512_DQ 175 | constexpr inline auto dq_ = true; 176 | #else 177 | constexpr inline auto dq_ = false; 178 | #endif 179 | 180 | #if defined(__AVX512ER__) 181 | #define SPY_SIMD_IS_X86_AVX512_ER 182 | constexpr inline auto er_ = true; 183 | #else 184 | constexpr inline auto er_ = false; 185 | #endif 186 | 187 | #if defined(__AVX512IFMA__) 188 | #define SPY_SIMD_IS_X86_AVX512_IFMA 189 | constexpr inline auto ifma_ = true; 190 | #else 191 | constexpr inline auto ifma_ = false; 192 | #endif 193 | 194 | #if defined(__AVX512PF__) 195 | #define SPY_SIMD_IS_X86_AVX512_PF 196 | constexpr inline auto pf_ = true; 197 | #else 198 | constexpr inline auto pf_ = false; 199 | #endif 200 | 201 | #if defined(__AVX512VL__) 202 | #define SPY_SIMD_IS_X86_AVX512_VL 203 | constexpr inline auto vl_ = true; 204 | #else 205 | constexpr inline auto vl_ = false; 206 | #endif 207 | 208 | #if defined(__AVX512VPOPCNTDQ__) 209 | #define SPY_SIMD_IS_X86_AVX512_POPCNTDQ 210 | constexpr inline auto popcntdq_ = true; 211 | #else 212 | constexpr inline auto popcntdq_ = false; 213 | #endif 214 | 215 | #if defined(__AVX5124FMAPS__) 216 | #define SPY_SIMD_IS_X86_AVX512_4FMAPS 217 | constexpr inline auto _4fmaps_ = true; 218 | #else 219 | constexpr inline auto _4fmaps_ = false; 220 | #endif 221 | 222 | #if defined(__AVX5124VNNIW__) 223 | #define SPY_SIMD_IS_X86_AVX512_VNNIW 224 | constexpr inline auto vnniw_ = true; 225 | #else 226 | constexpr inline auto vnniw_ = false; 227 | #endif 228 | 229 | #if defined(__AVX512VBMI__) 230 | #define SPY_SIMD_IS_X86_AVX512_VBMI 231 | constexpr inline auto vbmi_ = true; 232 | #else 233 | constexpr inline auto vbmi_ = false; 234 | #endif 235 | 236 | #if defined(__AVX512BF16__) 237 | #define SPY_SIMD_IS_X86_AVX512_BF16 238 | constexpr inline auto bf16_ = true; 239 | #else 240 | constexpr inline auto bf16_ = false; 241 | #endif 242 | 243 | #if defined(__AVX512BITALG__) 244 | #define SPY_SIMD_IS_X86_AVX512_BITALG 245 | constexpr inline auto bitalg_ = true; 246 | #else 247 | constexpr inline auto bitalg_ = false; 248 | #endif 249 | 250 | #if defined(__AVX512VBMI2__) 251 | #define SPY_SIMD_IS_X86_AVX512_VBMI2 252 | constexpr inline auto vbmi2_ = true; 253 | #else 254 | constexpr inline auto vbmi2_ = false; 255 | #endif 256 | 257 | #if defined(__AVX512VNNI__) 258 | #define SPY_SIMD_IS_X86_AVX512_VNNI 259 | constexpr inline auto vnni_ = true; 260 | #else 261 | constexpr inline auto vnni_ = false; 262 | #endif 263 | 264 | #if defined(__AVX512VP2INTERSECT__) 265 | #define SPY_SIMD_IS_X86_AVX512_VP2INTERSECT 266 | constexpr inline auto vpintersect_ = true; 267 | #else 268 | constexpr inline auto vpintersect_ = false; 269 | #endif 270 | } 271 | 272 | } 273 | -------------------------------------------------------------------------------- /test/unit/compiler.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | #include 11 | 12 | int main() 13 | { 14 | std::cout << "Check that detected compiler is correct: " << std::flush; 15 | { 16 | #if defined(__NVCC__) 17 | assert( spy::compiler == spy::nvcc_ ); 18 | assert( !(spy::compiler == spy::msvc_ )); 19 | assert( !(spy::compiler == spy::intel_ )); 20 | assert( !(spy::compiler == spy::dpcpp_ )); 21 | assert( !(spy::compiler == spy::clang_ )); 22 | assert( !(spy::compiler == spy::gcc_ )); 23 | assert( !(spy::compiler == spy::emscripten_)); 24 | #elif defined(_MSC_VER) 25 | assert( !(spy::compiler == spy::nvcc_ )); 26 | assert( spy::compiler == spy::msvc_ ); 27 | assert( !(spy::compiler == spy::intel_ )); 28 | assert( !(spy::compiler == spy::dpcpp_ )); 29 | assert( !(spy::compiler == spy::clang_ )); 30 | assert( !(spy::compiler == spy::gcc_ )); 31 | assert( !(spy::compiler == spy::emscripten_)); 32 | #elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) 33 | assert( !(spy::compiler == spy::nvcc_ )); 34 | assert( !(spy::compiler == spy::msvc_ )); 35 | assert( spy::compiler == spy::intel_ ); 36 | assert( !(spy::compiler == spy::dpcpp_ )); 37 | assert( !(spy::compiler == spy::clang_ )); 38 | assert( !(spy::compiler == spy::gcc_ )); 39 | assert( !(spy::compiler == spy::emscripten_)); 40 | #elif defined(__INTEL_LLVM_COMPILER) 41 | assert( !(spy::compiler == spy::nvcc_ )); 42 | assert( !(spy::compiler == spy::msvc_ )); 43 | assert( !(spy::compiler == spy::intel_ )); 44 | assert( spy::compiler == spy::dpcpp_ ); 45 | assert( !(spy::compiler == spy::clang_ )); 46 | assert( !(spy::compiler == spy::gcc_ )); 47 | assert( !(spy::compiler == spy::emscripten_)); 48 | #elif defined(__EMSCRIPTEN__) 49 | assert( !(spy::compiler == spy::nvcc_ )); 50 | assert( !(spy::compiler == spy::msvc_ )); 51 | assert( !(spy::compiler == spy::intel_ )); 52 | assert( !(spy::compiler == spy::dpcpp_ )); 53 | assert( !(spy::compiler == spy::clang_ )); 54 | assert( !(spy::compiler == spy::gcc_ )); 55 | assert( spy::compiler == spy::emscripten_); 56 | #elif defined(__clang__) 57 | assert( !(spy::compiler == spy::nvcc_ )); 58 | assert( !(spy::compiler == spy::msvc_ )); 59 | assert( !(spy::compiler == spy::intel_ )); 60 | assert( !(spy::compiler == spy::dpcpp_ )); 61 | assert( spy::compiler == spy::clang_ ); 62 | assert( !(spy::compiler == spy::gcc_ )); 63 | assert( !(spy::compiler == spy::emscripten_)); 64 | #elif defined(__GNUC__) 65 | assert( !(spy::compiler == spy::nvcc_ )); 66 | assert( !(spy::compiler == spy::msvc_ )); 67 | assert( !(spy::compiler == spy::intel_ )); 68 | assert( !(spy::compiler == spy::dpcpp_ )); 69 | assert( !(spy::compiler == spy::clang_ )); 70 | assert( spy::compiler == spy::gcc_ ); 71 | assert( !(spy::compiler == spy::emscripten_)); 72 | #endif 73 | } 74 | std::cout << "Done." << std::endl; 75 | std::cout << "Detected compiler: " << spy::compiler << std::endl; 76 | 77 | std::cout << "Check that detected compiler version is correct: " << std::flush; 78 | { 79 | using namespace spy::literal; 80 | 81 | #if defined(__NVCC__) 82 | assert( spy::compiler >= 6'0_nvcc ); 83 | assert( !(spy::compiler >= 19'5_msvc)); 84 | assert( !(spy::compiler >= 19_intel )); 85 | assert( !(spy::compiler >= 2023'1_dpcpp )); 86 | assert( !(spy::compiler >= 3'9_clang)); 87 | assert( !(spy::compiler >= 7'2_gcc )); 88 | assert( !(spy::compiler >= 3'1_em )); 89 | #elif defined(_MSC_VER) 90 | assert( !(spy::compiler >= 6'0_nvcc )); 91 | assert( spy::compiler >= 19'5_msvc ); 92 | assert( !(spy::compiler >= 19_intel )); 93 | assert( !(spy::compiler >= 2023'1_dpcpp )); 94 | assert( !(spy::compiler >= 3'9_clang)); 95 | assert( !(spy::compiler >= 7'2_gcc )); 96 | assert( !(spy::compiler >= 3'1_em )); 97 | #elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) 98 | assert( !(spy::compiler >= 6'0_nvcc )); 99 | assert( !(spy::compiler >= 19'5_msvc)); 100 | assert( spy::compiler >= 19_intel ); 101 | assert( !(spy::compiler >= 2023'1_dpcpp )); 102 | assert( !(spy::compiler >= 3'9_clang)); 103 | assert( !(spy::compiler >= 7'2_gcc )); 104 | assert( !(spy::compiler >= 3'1_em )); 105 | #elif defined(__INTEL_LLVM_COMPILER) 106 | assert( !(spy::compiler >= 6'0_nvcc )); 107 | assert( !(spy::compiler >= 19'5_msvc)); 108 | assert( !(spy::compiler >= 19_intel )); 109 | assert( spy::compiler >= 2023'1_dpcpp); 110 | assert( !(spy::compiler >= 3'9_clang)); 111 | assert( !(spy::compiler >= 7'2_gcc )); 112 | assert( !(spy::compiler >= 3'1_em )); 113 | #elif defined(__EMSCRIPTEN__) 114 | assert( !(spy::compiler >= 6'0_nvcc )); 115 | assert( !(spy::compiler >= 19'5_msvc)); 116 | assert( !(spy::compiler >= 19_intel )); 117 | assert( !(spy::compiler >= 2023'1_dpcpp )); 118 | assert( !(spy::compiler >= 3'9_clang)); 119 | assert( !(spy::compiler >= 7'2_gcc )); 120 | assert( spy::compiler >= 3'1_em ); 121 | #elif defined(__clang__) 122 | assert( !(spy::compiler >= 6'0_nvcc )); 123 | assert( !(spy::compiler >= 19'5_msvc)); 124 | assert( !(spy::compiler >= 19_intel )); 125 | assert( !(spy::compiler >= 2023'1_dpcpp )); 126 | assert( spy::compiler >= 3'9_clang ); 127 | assert( !(spy::compiler >= 7'2_gcc )); 128 | assert( !(spy::compiler >= 3'1_em )); 129 | #elif defined(__GNUC__ ) 130 | assert( !(spy::compiler >= 6'0_nvcc )); 131 | assert( !(spy::compiler >= 19'5_msvc)); 132 | assert( !(spy::compiler >= 19_intel )); 133 | assert( !(spy::compiler >= 2023'1_dpcpp )); 134 | assert( !(spy::compiler >= 3'9_clang)); 135 | assert( spy::compiler >= 7'2_gcc ); 136 | assert( !(spy::compiler >= 3'1_em )); 137 | #endif 138 | } 139 | std::cout << "Done." << std::endl; 140 | 141 | std::cout << "Check that detected constexpr selection on exact compiler is correct: " << std::flush; 142 | { 143 | using namespace spy::literal; 144 | 145 | #if defined(__NVCC__) 146 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_nvcc; 147 | #elif defined(_MSC_VER) 148 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_msvc; 149 | #elif defined(__INTEL_LLVM_COMPILER) 150 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_dpcpp; 151 | #elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) 152 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_intel; 153 | #elif defined(__EMSCRIPTEN___) 154 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_em; 155 | #elif defined(__clang__) 156 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_clang; 157 | #elif defined(__GNUC__) 158 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = 1'42'1337_gcc; 159 | #else 160 | [[maybe_unused]] auto constexpr wrong_constexpr_behavior = false; 161 | #endif 162 | 163 | if constexpr(spy::compiler) 164 | { 165 | assert( !bool(wrong_constexpr_behavior) ); 166 | } 167 | else 168 | { 169 | assert( bool(wrong_constexpr_behavior) ); 170 | } 171 | } 172 | std::cout << "Done." << std::endl; 173 | } 174 | -------------------------------------------------------------------------------- /test/unit/simd.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /** 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | **/ 7 | //================================================================================================== 8 | #include 9 | #include 10 | #include 11 | 12 | int main() 13 | { 14 | std::cout << "Supported SIMD instructions set: " << spy::simd_instruction_set << std::endl; 15 | std::cout << "Supported SIMD instructions set: " << typeid(spy::simd_instruction_set).name() << std::endl; 16 | std::cout << "Check that X86 SIMD extension detection is correct: " << std::endl; 17 | { 18 | std::cout << "X86 SIMD status: " << std::boolalpha << (spy::simd_instruction_set == spy::x86_simd_) << std::endl; 19 | std::cout << "SSE1 status: " << std::boolalpha << (spy::simd_instruction_set >= spy::sse1_ ) << std::endl; 20 | std::cout << "SSE2 status: " << std::boolalpha << (spy::simd_instruction_set >= spy::sse2_ ) << std::endl; 21 | std::cout << "SSE3 status: " << std::boolalpha << (spy::simd_instruction_set >= spy::sse3_ ) << std::endl; 22 | std::cout << "SSE4.1 status: " << std::boolalpha << (spy::simd_instruction_set >= spy::sse41_ ) << std::endl; 23 | std::cout << "SSE4.2 status: " << std::boolalpha << (spy::simd_instruction_set >= spy::sse42_ ) << std::endl; 24 | std::cout << "AVX status: " << std::boolalpha << (spy::simd_instruction_set >= spy::avx_ ) << std::endl; 25 | std::cout << "AVX2 status: " << std::boolalpha << (spy::simd_instruction_set >= spy::avx2_ ) << std::endl; 26 | std::cout << "FMA3 support: " << std::boolalpha << (spy::supports::fma_ ) << std::endl; 27 | std::cout << "FMA4 support: " << std::boolalpha << (spy::supports::fma4_ ) << std::endl; 28 | std::cout << "XOP support: " << std::boolalpha << (spy::supports::xop_ ) << std::endl; 29 | std::cout << "AVX512 status: " << std::boolalpha << (spy::simd_instruction_set >= spy::avx512_ ) << std::endl; 30 | std::cout << "|-BW support: " << std::boolalpha << (spy::supports::avx512::bw_ ) << std::endl; 31 | std::cout << "|-CD support: " << std::boolalpha << (spy::supports::avx512::cd_ ) << std::endl; 32 | std::cout << "|-DQ support: " << std::boolalpha << (spy::supports::avx512::dq_ ) << std::endl; 33 | std::cout << "|-ER support: " << std::boolalpha << (spy::supports::avx512::er_ ) << std::endl; 34 | std::cout << "|-IFMA support: " << std::boolalpha << (spy::supports::avx512::ifma_ ) << std::endl; 35 | std::cout << "|-PF support: " << std::boolalpha << (spy::supports::avx512::pf_ ) << std::endl; 36 | std::cout << "|-VL support: " << std::boolalpha << (spy::supports::avx512::vl_ ) << std::endl; 37 | std::cout << "|-POPCNTDQ support: " << std::boolalpha << (spy::supports::avx512::popcntdq_ ) << std::endl; 38 | std::cout << "|-4FMAPS support: " << std::boolalpha << (spy::supports::avx512::_4fmaps_ ) << std::endl; 39 | std::cout << "|-VNNIW support: " << std::boolalpha << (spy::supports::avx512::vnniw_ ) << std::endl; 40 | std::cout << "|-VBMI support: " << std::boolalpha << (spy::supports::avx512::vbmi_ ) << std::endl; 41 | std::cout << "|-BF16 support: " << std::boolalpha << (spy::supports::avx512::bf16_ ) << std::endl; 42 | std::cout << "|-BITALG support: " << std::boolalpha << (spy::supports::avx512::bitalg_ ) << std::endl; 43 | std::cout << "|-VBMI2 support: " << std::boolalpha << (spy::supports::avx512::vbmi2_ ) << std::endl; 44 | std::cout << "|-VNNI support: " << std::boolalpha << (spy::supports::avx512::vnni_ ) << std::endl; 45 | std::cout << "|-VPINTERSECT support: " << std::boolalpha << (spy::supports::avx512::vpintersect_ ) << std::endl; 46 | } 47 | std::cout << std::endl; 48 | 49 | std::cout << "Check that ARM SIMD extension detection is correct: " << std::endl; 50 | { 51 | std::cout << "ARM SIMD status: " << std::boolalpha << (spy::simd_instruction_set == spy::arm_simd_ ) << std::endl; 52 | std::cout << "NEON status: " << std::boolalpha << (spy::simd_instruction_set >= spy::neon_ ) << std::endl; 53 | std::cout << "ASIMD status: " << std::boolalpha << (spy::simd_instruction_set >= spy::asimd_) << std::endl; 54 | 55 | std::cout << "SVE status: " << std::boolalpha << (spy::simd_instruction_set == spy::sve_ ) << std::endl; 56 | std::cout << "SVE (fixed) status: " << std::boolalpha << (spy::simd_instruction_set == spy::fixed_sve_ ) << std::endl; 57 | std::cout << "SVE2 status: " << std::boolalpha << (spy::simd_instruction_set == spy::sve2_) << std::endl; 58 | std::cout << "SVE2 (fixed) status: " << std::boolalpha << (spy::simd_instruction_set == spy::fixed_sve2_ ) << std::endl; 59 | if constexpr(spy::simd_instruction_set >= spy::sve_ ) 60 | { 61 | if constexpr(spy::simd_instruction_set.has_fixed_cardinal()) 62 | { 63 | std::cout << "SVE register size: " << spy::simd_instruction_set.width << " bits" << std::endl; 64 | } 65 | } 66 | } 67 | std::cout << std::endl; 68 | 69 | std::cout << "Check that PPC SIMD extension detection is correct: " << std::endl; 70 | { 71 | std::cout << "PPC SIMD status: " << std::boolalpha << (spy::simd_instruction_set == spy::ppc_simd_ ) << std::endl; 72 | std::cout << "VMX (Any ISA) status: " << std::boolalpha << (spy::simd_instruction_set >= spy::vmx_ ) << std::endl; 73 | std::cout << " |- ISA v2.03 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vmx_2_03_ ) << std::endl; 74 | std::cout << " |- ISA v2.05 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vmx_2_05_ ) << std::endl; 75 | std::cout << " |- ISA v2.06 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vmx_2_06_ ) << std::endl; 76 | std::cout << " |- ISA v2.07 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vmx_2_07_ ) << std::endl; 77 | std::cout << " |- ISA v3.00 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vmx_3_00_ ) << std::endl; 78 | std::cout << " |- ISA v3.01 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vmx_3_01_ ) << std::endl; 79 | std::cout << "VSX (Any ISA) status: " << std::boolalpha << (spy::simd_instruction_set >= spy::vsx_ ) << std::endl; 80 | std::cout << " |- ISA v2.06 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vsx_2_06_ ) << std::endl; 81 | std::cout << " |- ISA v2.07 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vsx_2_07_ ) << std::endl; 82 | std::cout << " |- ISA v3.00 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vsx_3_00_ ) << std::endl; 83 | std::cout << " |- ISA v3.01 support : " << std::boolalpha << (spy::simd_instruction_set >= spy::vsx_3_01_ ) << std::endl; 84 | } 85 | std::cout << std::endl; 86 | 87 | std::cout << "Check that WASM SIMD extension detection is correct: " << std::endl; 88 | { 89 | std::cout << "WASM status: " << std::boolalpha << (spy::simd_instruction_set == spy::wasm_simd_ ) << std::endl; 90 | std::cout << "SIMD128 status: " << std::boolalpha << (spy::simd_instruction_set >= spy::simd128_ ) << std::endl; 91 | } 92 | std::cout << std::endl; 93 | 94 | std::cout << "Check that RISC-V SIMD extension detection is correct: " << std::endl; 95 | { 96 | std::cout << "RISC-V status: " << std::boolalpha << (spy::simd_instruction_set == spy::riscv_simd_) << std::endl; 97 | std::cout << "RVV status: " << std::boolalpha << (spy::simd_instruction_set >= spy::rvv_ ) << std::endl; 98 | std::cout << "RVV (fixed) status: " << std::boolalpha << (spy::simd_instruction_set >= spy::fixed_rvv_ ) << std::endl; 99 | if constexpr(spy::simd_instruction_set >= spy::rvv_ ) 100 | { 101 | if constexpr(spy::simd_instruction_set.has_fixed_cardinal()) 102 | { 103 | std::cout << "RVV register size: " << spy::simd_instruction_set.width << " bits" << std::endl; 104 | } 105 | } 106 | } 107 | std::cout << std::endl; 108 | } 109 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | ## ------------------------------------------------------------------------------------------------- 2 | ## SPY - C++ Informations Broker 3 | ## Copyright: SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ## ------------------------------------------------------------------------------------------------- 6 | BasedOnStyle: Microsoft 7 | AccessModifierOffset: -2 8 | AlignAfterOpenBracket: Align 9 | AlignArrayOfStructures: None 10 | AlignConsecutiveAssignments: 11 | AcrossEmptyLines: false 12 | AcrossComments: false 13 | AlignCompound: false 14 | AlignFunctionPointers: false 15 | PadOperators: true 16 | AlignConsecutiveBitFields: 17 | Enabled: false 18 | AcrossEmptyLines: false 19 | AcrossComments: false 20 | AlignCompound: false 21 | AlignFunctionPointers: false 22 | PadOperators: false 23 | AlignConsecutiveDeclarations: 24 | Enabled: false 25 | AcrossEmptyLines: false 26 | AcrossComments: false 27 | AlignCompound: false 28 | AlignFunctionPointers: false 29 | PadOperators: false 30 | AlignConsecutiveMacros: 31 | Enabled: false 32 | AcrossEmptyLines: false 33 | AcrossComments: false 34 | AlignCompound: false 35 | AlignFunctionPointers: false 36 | PadOperators: false 37 | AlignConsecutiveShortCaseStatements: 38 | Enabled: false 39 | AcrossEmptyLines: false 40 | AcrossComments: false 41 | AlignCaseArrows: false 42 | AlignCaseColons: false 43 | AlignConsecutiveTableGenBreakingDAGArgColons: 44 | Enabled: false 45 | AcrossEmptyLines: false 46 | AcrossComments: false 47 | AlignCompound: false 48 | AlignFunctionPointers: false 49 | PadOperators: false 50 | AlignConsecutiveTableGenCondOperatorColons: 51 | Enabled: false 52 | AcrossEmptyLines: false 53 | AcrossComments: false 54 | AlignCompound: false 55 | AlignFunctionPointers: false 56 | PadOperators: false 57 | AlignConsecutiveTableGenDefinitionColons: 58 | Enabled: false 59 | AcrossEmptyLines: false 60 | AcrossComments: false 61 | AlignCompound: false 62 | AlignFunctionPointers: false 63 | PadOperators: false 64 | AlignEscapedNewlines: Right 65 | AlignOperands: Align 66 | AlignTrailingComments: 67 | Kind: Always 68 | OverEmptyLines: 0 69 | AllowAllArgumentsOnNextLine: false 70 | AllowAllParametersOfDeclarationOnNextLine: true 71 | AllowBreakBeforeNoexceptSpecifier: Always 72 | AllowShortBlocksOnASingleLine: Always 73 | AllowShortCaseExpressionOnASingleLine: true 74 | AllowShortCaseLabelsOnASingleLine: false 75 | AllowShortCompoundRequirementOnASingleLine: true 76 | AllowShortEnumsOnASingleLine: false 77 | AllowShortFunctionsOnASingleLine: Inline 78 | AllowShortIfStatementsOnASingleLine: AllIfsAndElse 79 | AllowShortLambdasOnASingleLine: All 80 | AllowShortLoopsOnASingleLine: true 81 | AlwaysBreakAfterDefinitionReturnType: None 82 | AlwaysBreakBeforeMultilineStrings: false 83 | AttributeMacros: 84 | - __capability 85 | BinPackArguments: true 86 | BinPackParameters: false 87 | BitFieldColonSpacing: Both 88 | BraceWrapping: 89 | AfterCaseLabel: false 90 | AfterClass: true 91 | AfterControlStatement: Always 92 | AfterEnum: true 93 | AfterFunction: true 94 | AfterNamespace: true 95 | AfterObjCDeclaration: true 96 | AfterStruct: true 97 | AfterUnion: false 98 | AfterExternBlock: true 99 | BeforeCatch: true 100 | BeforeElse: true 101 | BeforeLambdaBody: false 102 | BeforeWhile: false 103 | IndentBraces: false 104 | SplitEmptyFunction: true 105 | SplitEmptyRecord: true 106 | SplitEmptyNamespace: true 107 | BreakAdjacentStringLiterals: true 108 | BreakAfterAttributes: Leave 109 | BreakAfterJavaFieldAnnotations: false 110 | BreakAfterReturnType: None 111 | BreakArrays: false 112 | BreakBeforeBinaryOperators: None 113 | BreakBeforeBraces: Custom 114 | BreakBeforeConceptDeclarations: Always 115 | BreakBeforeInlineASMColon: OnlyMultiline 116 | BreakBeforeTernaryOperators: true 117 | BreakConstructorInitializers: BeforeColon 118 | BreakFunctionDefinitionParameters: false 119 | BreakInheritanceList: BeforeColon 120 | BreakStringLiterals: true 121 | BreakTemplateDeclarations: MultiLine 122 | ColumnLimit: 120 123 | CommentPragmas: "" 124 | CompactNamespaces: false 125 | ConstructorInitializerIndentWidth: 2 126 | ContinuationIndentWidth: 2 127 | Cpp11BracedListStyle: true 128 | DerivePointerAlignment: false 129 | DisableFormat: false 130 | EmptyLineAfterAccessModifier: Never 131 | EmptyLineBeforeAccessModifier: LogicalBlock 132 | ExperimentalAutoDetectBinPacking: false 133 | FixNamespaceComments: false 134 | IncludeBlocks: Regroup 135 | IncludeCategories: 136 | - Regex: 137 | Priority: 1 138 | CaseSensitive: true 139 | SortPriority: 1 140 | - Regex: 141 | Priority: 2 142 | CaseSensitive: true 143 | SortPriority: 2 144 | - Regex: .* 145 | Priority: 3 146 | CaseSensitive: true 147 | SortPriority: 3 148 | IncludeIsMainRegex: "" 149 | IncludeIsMainSourceRegex: "" 150 | IndentAccessModifiers: false 151 | IndentCaseBlocks: false 152 | IndentCaseLabels: false 153 | IndentExternBlock: AfterExternBlock 154 | IndentGotoLabels: true 155 | IndentPPDirectives: None 156 | IndentRequiresClause: false 157 | IndentWidth: 2 158 | IndentWrappedFunctionNames: false 159 | InsertBraces: false 160 | InsertNewlineAtEOF: true 161 | InsertTrailingCommas: None 162 | IntegerLiteralSeparator: 163 | Binary: 0 164 | BinaryMinDigits: 0 165 | Decimal: 0 166 | DecimalMinDigits: 0 167 | Hex: 0 168 | HexMinDigits: 0 169 | JavaScriptQuotes: Leave 170 | JavaScriptWrapImports: true 171 | KeepEmptyLines: 172 | AtEndOfFile: false 173 | AtStartOfBlock: true 174 | AtStartOfFile: true 175 | LambdaBodyIndentation: Signature 176 | LineEnding: LF 177 | MacroBlockBegin: "" 178 | MacroBlockEnd: "" 179 | MainIncludeChar: AngleBracket 180 | MaxEmptyLinesToKeep: 1 181 | NamespaceIndentation: All 182 | ObjCBinPackProtocolList: Auto 183 | ObjCBlockIndentWidth: 2 184 | ObjCBreakBeforeNestedBlockParam: true 185 | ObjCSpaceAfterProperty: false 186 | ObjCSpaceBeforeProtocolList: true 187 | PPIndentWidth: -1 188 | PackConstructorInitializers: BinPack 189 | PenaltyBreakAssignment: 2 190 | PenaltyBreakBeforeFirstCallParameter: 19 191 | PenaltyBreakComment: 300 192 | PenaltyBreakFirstLessLess: 120 193 | PenaltyBreakOpenParenthesis: 0 194 | PenaltyBreakScopeResolution: 500 195 | PenaltyBreakString: 1000 196 | PenaltyBreakTemplateDeclaration: 10 197 | PenaltyExcessCharacter: 1000000 198 | PenaltyIndentedWhitespace: 0 199 | PenaltyReturnTypeOnItsOwnLine: 1000 200 | PointerAlignment: Left 201 | QualifierAlignment: Custom 202 | ReferenceAlignment: Pointer 203 | ReflowComments: true 204 | RemoveBracesLLVM: false 205 | RemoveParentheses: ReturnStatement 206 | RemoveSemicolon: false 207 | RequiresClausePosition: OwnLine 208 | RequiresExpressionIndentation: OuterScope 209 | SeparateDefinitionBlocks: Always 210 | ShortNamespaceLines: 1 211 | SkipMacroDefinitionBody: false 212 | SortIncludes: CaseSensitive 213 | SortJavaStaticImport: Before 214 | SortUsingDeclarations: LexicographicNumeric 215 | SpaceAfterCStyleCast: false 216 | SpaceAfterLogicalNot: false 217 | SpaceAfterTemplateKeyword: false 218 | SpaceAroundPointerQualifiers: Default 219 | SpaceBeforeAssignmentOperators: true 220 | SpaceBeforeCaseColon: false 221 | SpaceBeforeCpp11BracedList: false 222 | SpaceBeforeCtorInitializerColon: true 223 | SpaceBeforeInheritanceColon: true 224 | SpaceBeforeJsonColon: false 225 | SpaceBeforeParens: ControlStatements 226 | SpaceBeforeParensOptions: 227 | AfterControlStatements: true 228 | AfterForeachMacros: true 229 | AfterFunctionDeclarationName: false 230 | AfterFunctionDefinitionName: false 231 | AfterIfMacros: true 232 | AfterOverloadedOperator: false 233 | AfterPlacementOperator: true 234 | AfterRequiresInClause: false 235 | AfterRequiresInExpression: false 236 | BeforeNonEmptyParentheses: false 237 | SpaceBeforeRangeBasedForLoopColon: true 238 | SpaceBeforeSquareBrackets: false 239 | SpaceInEmptyBlock: false 240 | SpacesBeforeTrailingComments: 1 241 | SpacesInAngles: Never 242 | SpacesInContainerLiterals: true 243 | SpacesInLineCommentPrefix: 244 | Minimum: 1 245 | Maximum: -1 246 | SpacesInParens: Never 247 | SpacesInParensOptions: 248 | ExceptDoubleParentheses: false 249 | InConditionalStatements: false 250 | InCStyleCasts: false 251 | InEmptyParentheses: false 252 | Other: false 253 | SpacesInSquareBrackets: false 254 | Standard: c++20 255 | TabWidth: 2 256 | TableGenBreakInsideDAGArg: DontBreak 257 | UseTab: Never 258 | VerilogBreakBetweenInstancePorts: true 259 | Language: Cpp 260 | QualifierOrder: 261 | - inline 262 | - static 263 | - type 264 | - const 265 | -------------------------------------------------------------------------------- /include/spy/compiler.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | 12 | #include 13 | 14 | #if defined __has_include 15 | #if __has_include() 16 | #include 17 | #endif 18 | #endif 19 | 20 | namespace spy::_ 21 | { 22 | enum class compilers 23 | { 24 | undefined_ = -1, 25 | msvc_, 26 | intel_, 27 | clang_, 28 | gcc_, 29 | emscripten_, 30 | dpcpp_, 31 | nvcc_ 32 | }; 33 | 34 | template struct compilers_info 35 | { 36 | static constexpr compilers vendor = Compiler; 37 | static constexpr version_id version = {}; 38 | 39 | inline constexpr explicit operator bool() const noexcept; 40 | 41 | template constexpr bool operator==(compilers_info const&) const noexcept 42 | { 43 | return C2 == vendor; 44 | } 45 | 46 | template 47 | constexpr bool operator==(compilers_info const& c2) const noexcept 48 | { 49 | return C2 == vendor && version == c2.version; 50 | } 51 | 52 | template 53 | constexpr std::partial_ordering operator<=>(compilers_info const& c2) const noexcept 54 | { 55 | if constexpr (vendor == C2) return version <=> c2.version; 56 | else return std::partial_ordering::unordered; 57 | } 58 | }; 59 | 60 | template<_::stream OS, compilers C, int M, int N, int P> auto& operator<<(OS& os, compilers_info const& c) 61 | { 62 | if (C == compilers::nvcc_) return os << "NVIDIA CUDA Compiler " << c.version; 63 | if (C == compilers::msvc_) return os << "Microsoft Visual Studio " << c.version; 64 | if (C == compilers::intel_) return os << "Intel(R) C++ Compiler " << c.version; 65 | if (C == compilers::dpcpp_) return os << "Intel(R) oneAPI DPC++/C++ Compiler " << c.version; 66 | if (C == compilers::clang_) return os << "clang " << c.version; 67 | if (C == compilers::gcc_) return os << "g++ " << c.version; 68 | if (C == compilers::emscripten_) return os << "Emscripten " << c.version; 69 | 70 | return os << "Undefined " << c.version; 71 | } 72 | 73 | template using msvc_t = compilers_info; 74 | template using intel_t = compilers_info; 75 | template using dpcpp_t = compilers_info; 76 | template using nvcc_t = compilers_info; 77 | template using clang_t = compilers_info; 78 | template using gcc_t = compilers_info; 79 | template using emscripten_t = compilers_info; 80 | } 81 | 82 | namespace spy 83 | { 84 | //================================================================================================ 85 | // Compiler detection object type 86 | //================================================================================================ 87 | #if defined(__NVCC__) 88 | #define SPY_COMPILER_IS_NVCC 89 | using compiler_type = _::nvcc_t<__CUDACC_VER_MAJOR__, __CUDACC_VER_MINOR__, 0>; 90 | #elif defined(_MSC_VER) 91 | #define SPY_COMPILER_IS_MSVC 92 | using compiler_type = _::msvc_t<_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 100000>; 93 | #elif defined(__INTEL_LLVM_COMPILER) 94 | #define SPY_COMPILER_IS_INTEL_DPCPP 95 | #define SPY0 __INTEL_LLVM_COMPILER 96 | using compiler_type = _::dpcpp_t; 97 | #undef SPY0 98 | #elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) 99 | #define SPY_COMPILER_IS_INTEL 100 | #define SPY0 __INTEL_COMPILER 101 | using compiler_type = _::intel_t<(SPY0 / 100) % 100, SPY0 % 100, __INTEL_COMPILER_UPDATE>; 102 | #undef SPY0 103 | #elif defined(__EMSCRIPTEN__) 104 | #define SPY_COMPILER_IS_CLANG 105 | using compiler_type = _::emscripten_t<__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__>; 106 | #undef SPY0 107 | #elif defined(__clang__) 108 | #define SPY_COMPILER_IS_CLANG 109 | using compiler_type = _::clang_t<__clang_major__, __clang_minor__, __clang_patchlevel__>; 110 | #elif defined(__GNUC__) 111 | #define SPY_COMPILER_IS_GCC 112 | using compiler_type = _::gcc_t<__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__>; 113 | #else 114 | #define SPY_COMPILER_IS_UNKNOWN 115 | using compiler_type = _::compilers_info; 116 | #endif 117 | 118 | //================================================================================================ 119 | //! @ingroup api 120 | //! @brief Compiler reporting value 121 | //! 122 | //! The `spy::compiler` object can be compared to any other compiler related value to verify 123 | //! if the code being compiled with a specific compiler. 124 | //! 125 | //! Any compiler related value can be checked for equality or ordering for a given version. The targeted 126 | //! version is then specified using a compiler-dependent literal. 127 | //! 128 | //! Additionally, any of the compiler related value are convertible to `bool`. They evaluates to `true` if they 129 | //! matches the correct compiler currently used. 130 | //! 131 | //! @groupheader{Supported Value} 132 | //! 133 | //! Name | Compiler 134 | //! ----------------- | ------------- 135 | //! `spy::clang` | Clang 136 | //! `spy::dpcpp` | Intel DPC++/ICPX 137 | //! `spy::emscripten` | Emscripten 138 | //! `spy::gcc` | G++ 139 | //! `spy::intel` | Intel ICC 140 | //! `spy::msvc` | Microsoft Visual Studio 141 | //! `spy::nvcc` | NVIDIA NVCC 142 | //! 143 | //! @groupheader{Example} 144 | //! @godbolt{samples/compiler.cpp} 145 | //================================================================================================ 146 | constexpr inline compiler_type compiler; 147 | } 148 | 149 | namespace spy::_ 150 | { 151 | template inline constexpr compilers_info::operator bool() const noexcept 152 | { 153 | return spy::compiler == *this; 154 | } 155 | } 156 | 157 | namespace spy 158 | { 159 | //================================================================================================ 160 | // Compilers detector stand-alone instances 161 | //================================================================================================ 162 | constexpr inline auto nvcc_ = _::nvcc_t<-1, 0, 0>{}; 163 | constexpr inline auto msvc_ = _::msvc_t<-1, 0, 0>{}; 164 | constexpr inline auto intel_ = _::intel_t<-1, 0, 0>{}; 165 | constexpr inline auto dpcpp_ = _::dpcpp_t<-1, 0, 0>{}; 166 | constexpr inline auto clang_ = _::clang_t<-1, 0, 0>{}; 167 | constexpr inline auto gcc_ = _::gcc_t<-1, 0, 0>{}; 168 | constexpr inline auto emscripten_ = _::emscripten_t<-1, 0, 0>{}; 169 | } 170 | 171 | namespace spy::literal 172 | { 173 | //! @ingroup api 174 | //! @brief User-defined suffix for NVCC version definition 175 | template constexpr auto operator""_nvcc() 176 | { 177 | return _::literal_wrap<_::nvcc_t, c...>(); 178 | } 179 | 180 | //! @ingroup api 181 | //! @brief User-defined suffix for MSVC version definition 182 | template constexpr auto operator""_msvc() 183 | { 184 | return _::literal_wrap<_::msvc_t, c...>(); 185 | } 186 | 187 | //! @ingroup api 188 | //! @brief User-defined suffix for Intel ICC version definition 189 | template constexpr auto operator""_intel() 190 | { 191 | return _::literal_wrap<_::intel_t, c...>(); 192 | } 193 | 194 | //! @ingroup api 195 | //! @brief User-defined suffix for Intel DCP++/ICPX version definition 196 | template constexpr auto operator""_dpcpp() 197 | { 198 | return _::literal_wrap<_::dpcpp_t, c...>(); 199 | } 200 | 201 | //! @ingroup api 202 | //! @brief User-defined suffix for Clang version definition 203 | template constexpr auto operator""_clang() 204 | { 205 | return _::literal_wrap<_::clang_t, c...>(); 206 | } 207 | 208 | //! @ingroup api 209 | //! @brief User-defined suffix for G++ version definition 210 | template constexpr auto operator""_gcc() 211 | { 212 | return _::literal_wrap<_::gcc_t, c...>(); 213 | } 214 | 215 | //! @ingroup api 216 | //! @brief User-defined suffix for Emscripten version definition 217 | template constexpr auto operator""_em() 218 | { 219 | return _::literal_wrap<_::emscripten_t, c...>(); 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /doc/spy.tag: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | literal 5 | namespaceliteral.html 6 | 7 | 8 | spy 9 | namespacespy.html 10 | 11 | constexpr arch_type 12 | architecture 13 | group__api_gaad5f2aa34188a02b894a0d8c7e402d6e.html 14 | gaad5f2aa34188a02b894a0d8c7e402d6e 15 | 16 | 17 | 18 | constexpr compiler_type 19 | compiler 20 | group__api_ga2d96c18fea5b9a06ac37487ab570599d.html 21 | ga2d96c18fea5b9a06ac37487ab570599d 22 | 23 | 24 | 25 | constexpr auto 26 | data_model 27 | group__api_gaa091fe192a7f9d0d164cf7546083200d.html 28 | gaa091fe192a7f9d0d164cf7546083200d 29 | 30 | 31 | 32 | constexpr auto 33 | libc 34 | group__api_ga03dc3f2a9b02b025902f9df3b2db53ab.html 35 | ga03dc3f2a9b02b025902f9df3b2db53ab 36 | 37 | 38 | 39 | constexpr os_type 40 | operating_system 41 | group__api_gadb7c5be967e00cff21ae5b98cc12a7dc.html 42 | gadb7c5be967e00cff21ae5b98cc12a7dc 43 | 44 | 45 | 46 | constexpr auto 47 | simd_instruction_set 48 | group__api_ga45f64b82d4939d55865b0e6a311b2dde.html 49 | ga45f64b82d4939d55865b0e6a311b2dde 50 | 51 | 52 | 53 | constexpr auto 54 | stdlib 55 | group__api_gafe99b815db524eacf659ba8348ca2e0d.html 56 | gafe99b815db524eacf659ba8348ca2e0d 57 | 58 | 59 | 60 | 61 | supports 62 | namespacesupports.html 63 | 64 | 65 | api 66 | Main API 67 | group__api.html 68 | 69 | constexpr bool 70 | spy::supports::address_sanitizers_status 71 | group__api_ga37e2c07363dadf1eb40e89a9a91f8121.html 72 | ga37e2c07363dadf1eb40e89a9a91f8121 73 | 74 | 75 | 76 | constexpr arch_type 77 | spy::architecture 78 | group__api_gaad5f2aa34188a02b894a0d8c7e402d6e.html 79 | gaad5f2aa34188a02b894a0d8c7e402d6e 80 | 81 | 82 | 83 | constexpr compiler_type 84 | spy::compiler 85 | group__api_ga2d96c18fea5b9a06ac37487ab570599d.html 86 | ga2d96c18fea5b9a06ac37487ab570599d 87 | 88 | 89 | 90 | constexpr auto 91 | spy::supports::cuda 92 | group__api_gaad706954aedb6aaf6ff1a9858a971e00.html 93 | gaad706954aedb6aaf6ff1a9858a971e00 94 | 95 | 96 | 97 | constexpr auto 98 | spy::data_model 99 | group__api_gaa091fe192a7f9d0d164cf7546083200d.html 100 | gaa091fe192a7f9d0d164cf7546083200d 101 | 102 | 103 | 104 | constexpr auto 105 | spy::libc 106 | group__api_ga03dc3f2a9b02b025902f9df3b2db53ab.html 107 | ga03dc3f2a9b02b025902f9df3b2db53ab 108 | 109 | 110 | 111 | constexpr os_type 112 | spy::operating_system 113 | group__api_gadb7c5be967e00cff21ae5b98cc12a7dc.html 114 | gadb7c5be967e00cff21ae5b98cc12a7dc 115 | 116 | 117 | 118 | constexpr auto 119 | spy::supports::posix_ 120 | group__api_ga63eef44bc05ea6f77f278ba5b394ada8.html 121 | ga63eef44bc05ea6f77f278ba5b394ada8 122 | 123 | 124 | 125 | constexpr bool 126 | spy::supports::sanitizers_status 127 | group__api_ga28313e4f9673ea0f5d0ca44ffd1a967a.html 128 | ga28313e4f9673ea0f5d0ca44ffd1a967a 129 | 130 | 131 | 132 | constexpr auto 133 | spy::simd_instruction_set 134 | group__api_ga45f64b82d4939d55865b0e6a311b2dde.html 135 | ga45f64b82d4939d55865b0e6a311b2dde 136 | 137 | 138 | 139 | constexpr auto 140 | spy::stdlib 141 | group__api_gafe99b815db524eacf659ba8348ca2e0d.html 142 | gafe99b815db524eacf659ba8348ca2e0d 143 | 144 | 145 | 146 | constexpr auto 147 | spy::supports::sycl 148 | group__api_ga03e4a3ae6533a43cdf9bcbf1317707cd.html 149 | ga03e4a3ae6533a43cdf9bcbf1317707cd 150 | 151 | 152 | 153 | constexpr bool 154 | spy::supports::thread_sanitizers_status 155 | group__api_ga16591d3ea9aaa049682bfbedd519dc43.html 156 | ga16591d3ea9aaa049682bfbedd519dc43 157 | 158 | 159 | 160 | constexpr auto 161 | spy::literal::operator""_clang 162 | group__api.html 163 | gab3e0f11a5ec1b2963564755b84630970 164 | () 165 | 166 | 167 | constexpr auto 168 | spy::literal::operator""_cloud 169 | group__api.html 170 | ga1dc236e3cae2ef3c7ec23d45659b7b30 171 | () 172 | 173 | 174 | constexpr auto 175 | spy::literal::operator""_dpcpp 176 | group__api.html 177 | gab38166c11c2a99b2257e00630db206ec 178 | () 179 | 180 | 181 | constexpr auto 182 | spy::literal::operator""_em 183 | group__api.html 184 | ga8b0155c33f6f54c0d1d2dd498417c536 185 | () 186 | 187 | 188 | constexpr auto 189 | spy::literal::operator""_gcc 190 | group__api.html 191 | ga542b6a98ac5e95f906da14325a2064be 192 | () 193 | 194 | 195 | constexpr auto 196 | spy::literal::operator""_gnu 197 | group__api.html 198 | ga01fac6d9d1025344d16c3ab4fee137c8 199 | () 200 | 201 | 202 | constexpr auto 203 | spy::literal::operator""_intel 204 | group__api.html 205 | ga17b7828b022e763e749aebf056d24195 206 | () 207 | 208 | 209 | constexpr auto 210 | spy::literal::operator""_msvc 211 | group__api.html 212 | gaafdbca6599d9792e579da8041b5addcd 213 | () 214 | 215 | 216 | constexpr auto 217 | spy::literal::operator""_nvcc 218 | group__api.html 219 | ga39f9d138ef1adb4b5c12f4279878f1fc 220 | () 221 | 222 | 223 | constexpr auto 224 | spy::literal::operator""_uc 225 | group__api.html 226 | ga0c3666ca0bb5f551cc0103e355a28569 227 | () 228 | 229 | 230 | constexpr auto 231 | spy::literal::operator""_vms 232 | group__api.html 233 | ga772746f665f6dd13b9a6c8bd19564dab 234 | () 235 | 236 | 237 | constexpr auto 238 | spy::literal::operator""_zos 239 | group__api.html 240 | ga3c0e24636d16a543f4bf2ed64875eaeb 241 | () 242 | 243 | 244 | 245 | changelog 246 | Change Log 247 | changelog.html 248 | 249 | 250 | licence 251 | Licence 252 | licence.html 253 | 254 | 255 | setup 256 | Setup 257 | setup.html 258 | setup-source 259 | setup-standalone 260 | setup-fetchcontent 261 | setup-cpm 262 | 263 | 264 | index 265 | The C++ Information Broker 266 | index.html 267 | 268 | 269 | -------------------------------------------------------------------------------- /.github/workflows/unit.yml: -------------------------------------------------------------------------------- 1 | ##================================================================================================== 2 | ## SPY - C++ Informations Broker 3 | ## Copyright : SPY Project Contributors 4 | ## SPDX-License-Identifier: BSL-1.0 5 | ##================================================================================================== 6 | name: SPY - Unit Tests 7 | on: 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | concurrency: 13 | group: spy-unit-${{ github.ref }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | 18 | ################################################################################################## 19 | ## Mac OS X Targets 20 | ################################################################################################## 21 | macosx: 22 | runs-on: [macos-14] 23 | strategy: 24 | fail-fast: false 25 | matrix: 26 | cfg: 27 | - { comp: clang , arch: aarch64, mode: Debug } 28 | - { comp: clang , arch: aarch64, mode: Release } 29 | steps: 30 | - name: Fetch current branch 31 | uses: actions/checkout@v4.1.1 32 | - name: Running CMake for ${{ matrix.cfg.comp }} in ${{ matrix.cfg.mode }} mode 33 | run: | 34 | mkdir build && cd build 35 | cmake .. -DCMAKE_BUILD_TYPE="${{ matrix.cfg.mode }}" \ 36 | -DCMAKE_TOOLCHAIN_FILE=../test/toolchain/${{ matrix.cfg.comp }}.${{ matrix.cfg.arch }}.cmake 37 | - name: Compiling Unit Tests 38 | run: cd build && make spy-test -j 2 39 | - name: Running Unit Tests 40 | run: cd build && ctest --verbose --output-on-failure -j 2 41 | 42 | ################################################################################################## 43 | ## Windows Targets 44 | ################################################################################################## 45 | msvc: 46 | runs-on: [self-hosted, msvc] 47 | strategy: 48 | fail-fast: false 49 | matrix: 50 | cfg: 51 | - { mode: Debug } 52 | - { mode: Release } 53 | 54 | steps: 55 | - name: Fetch current branch 56 | uses: actions/checkout@v4.1.1 57 | - name: Running CMake for MSVC ${{ matrix.cfg.mode }} 58 | run: | 59 | mkdir build 60 | cd build 61 | cmake -G "Visual Studio 17 2022" -A x64 .. 62 | - name: Compiling Unit Tests 63 | run: | 64 | cd build 65 | cmake --build . --target spy-test --config ${{ matrix.cfg.mode }} --parallel 2 66 | - name: Running Tests 67 | run: | 68 | cd build 69 | ctest --verbose -C ${{ matrix.cfg.mode }} --output-on-failure 70 | 71 | clang-cl: 72 | runs-on: [windows-2022] 73 | strategy: 74 | fail-fast: false 75 | matrix: 76 | cfg: 77 | - { mode: Debug } 78 | - { mode: Release } 79 | 80 | steps: 81 | - name: Fetch current branch 82 | uses: actions/checkout@v4.1.1 83 | - name: Running CMake for Clang CL ${{ matrix.cfg.mode }} 84 | run: | 85 | mkdir build && cd build 86 | cmake -G "Visual Studio 17 2022" -T ClangCL -A x64 .. 87 | - name: Compiling Unit Tests 88 | run: | 89 | cd build 90 | cmake --build . --target spy-test --config ${{ matrix.cfg.mode }} --parallel 2 91 | - name: Running Tests 92 | run: | 93 | cd build 94 | ctest --verbose -C ${{ matrix.cfg.mode }} --output-on-failure 95 | 96 | ################################################################################################## 97 | ## WASM targets 98 | ################################################################################################## 99 | wasm: 100 | runs-on: ubuntu-latest 101 | container: 102 | image: ghcr.io/jfalcou/compilers:v9 103 | strategy: 104 | fail-fast: false 105 | matrix: 106 | cfg: 107 | - { comp: clang , arch: wasm, mode: Debug } 108 | - { comp: clang , arch: wasm, mode: Release } 109 | steps: 110 | - name: Fetch current branch 111 | uses: actions/checkout@v4.1.1 112 | - name: Running CMake for ${{ matrix.cfg.comp }} in ${{ matrix.cfg.mode }} mode 113 | run: | 114 | mkdir build && cd build 115 | cmake .. -G Ninja -DCMAKE_BUILD_TYPE="${{ matrix.cfg.mode }}" \ 116 | -DCMAKE_TOOLCHAIN_FILE=../test/toolchain/${{ matrix.cfg.comp }}.${{ matrix.cfg.arch }}.cmake 117 | - name: Compiling Unit Tests 118 | run: cd build && ninja spy-test -j 2 119 | - name: Running Unit Tests 120 | run: cd build && ctest --verbose --output-on-failure -j 2 121 | 122 | ################################################################################################## 123 | ## RISC-V targets 124 | ################################################################################################## 125 | riscv: 126 | runs-on: ubuntu-latest 127 | container: 128 | image: ghcr.io/jfalcou/compilers:v9 129 | strategy: 130 | fail-fast: false 131 | matrix: 132 | cfg: 133 | - { comp: clang , arch: rvv128, mode: Debug } 134 | - { comp: clang , arch: rvv128, mode: Release } 135 | steps: 136 | - name: Fetch current branch 137 | uses: actions/checkout@v4.1.1 138 | - name: Running CMake for ${{ matrix.cfg.comp }} in ${{ matrix.cfg.mode }} mode 139 | run: | 140 | mkdir build && cd build 141 | cmake .. -G Ninja -DCMAKE_BUILD_TYPE="${{ matrix.cfg.mode }}" \ 142 | -DCMAKE_TOOLCHAIN_FILE=../test/toolchain/${{ matrix.cfg.comp }}.${{ matrix.cfg.arch }}.cmake 143 | - name: Compiling Unit Tests 144 | run: cd build && ninja spy-test -j 2 145 | - name: Running Unit Tests 146 | run: cd build && ctest --verbose --output-on-failure -j 2 147 | 148 | ################################################################################################## 149 | ## CUDA targets 150 | ################################################################################################## 151 | nvcc: 152 | runs-on: self-hosted 153 | strategy: 154 | fail-fast: false 155 | matrix: 156 | cfg: 157 | - { comp: nvcc , opt: "" } 158 | - { comp: clang++ , opt: "--cuda-gpu-arch=sm_75 -lcudart_static -L/opt/cuda/lib64/ -ldl -lrt -pthread" } 159 | steps: 160 | - name: Fetch current branch 161 | uses: actions/checkout@v4.1.1 162 | - name: Compiling Unit Tests with ${{ matrix.cfg.comp }} 163 | run: | 164 | mkdir build && cd build 165 | ${{ matrix.cfg.comp }} ${{ matrix.cfg.opt }} ../test/unit/accelerator.cu -std=c++20 -I../include -o accelerator.device.exe 166 | ${{ matrix.cfg.comp }} ${{ matrix.cfg.opt }} ../test/unit/accelerator.cpp -std=c++20 -I../include -o accelerator.host.exe 167 | ${{ matrix.cfg.comp }} ${{ matrix.cfg.opt }} ../test/unit/arch.cpp -std=c++20 -I../include -o arch.exe 168 | ${{ matrix.cfg.comp }} ${{ matrix.cfg.opt }} ../test/unit/compiler.cpp -std=c++20 -I../include -o compiler.exe 169 | ${{ matrix.cfg.comp }} ${{ matrix.cfg.opt }} ../test/unit/data_model.cpp -std=c++20 -I../include -o data_model.exe 170 | ${{ matrix.cfg.comp }} ${{ matrix.cfg.opt }} ../test/unit/libc.cpp -std=c++20 -I../include -o libc.exe 171 | ${{ matrix.cfg.comp }} ${{ matrix.cfg.opt }} ../test/unit/os.cpp -std=c++20 -I../include -o os.exe 172 | ${{ matrix.cfg.comp }} ${{ matrix.cfg.opt }} ../test/unit/simd.cpp -std=c++20 -I../include -o simd.exe 173 | ${{ matrix.cfg.comp }} ${{ matrix.cfg.opt }} ../test/unit/stdlib.cpp -std=c++20 -I../include -o stdlib.exe 174 | - name: Running Unit Tests 175 | run: | 176 | cd build 177 | ./accelerator.device.exe && ./accelerator.host.exe && ./arch.exe && ./compiler.exe && ./data_model.exe && \ 178 | ./libc.exe && ./os.exe && ./simd.exe && ./stdlib.exe 179 | 180 | ################################################################################################## 181 | ## DPC++ Target 182 | ################################################################################################## 183 | dpcpp: 184 | runs-on: ubuntu-latest 185 | container: 186 | image: ghcr.io/jfalcou/compilers:sycl-v1 187 | strategy: 188 | fail-fast: false 189 | matrix: 190 | cfg: 191 | - { comp: dpcpp , arch: x86 , mode: Debug } 192 | - { comp: dpcpp , arch: sycl, mode: Debug } 193 | - { comp: dpcpp , arch: x86 , mode: Release } 194 | - { comp: dpcpp , arch: sycl, mode: Release } 195 | steps: 196 | - name: Fetch current branch 197 | uses: actions/checkout@v4.1.1 198 | - name: Running CMake for ${{ matrix.cfg.comp }} in ${{ matrix.cfg.mode }} mode 199 | run: | 200 | source /opt/intel/oneapi/setvars.sh 201 | mkdir build && cd build 202 | cmake .. -G Ninja -DCMAKE_BUILD_TYPE="${{ matrix.cfg.mode }}" \ 203 | -DCMAKE_TOOLCHAIN_FILE=../test/toolchain/${{ matrix.cfg.comp }}.${{ matrix.cfg.arch }}.cmake 204 | - name: Compiling Unit Tests 205 | run: cd build && ninja spy-test -j 2 206 | - name: Running Unit Tests 207 | run: cd build && ctest --verbose --output-on-failure -j 2 208 | 209 | ################################################################################################## 210 | ## Clang targets 211 | ################################################################################################## 212 | clang: 213 | runs-on: ubuntu-latest 214 | container: 215 | image: ghcr.io/jfalcou/compilers:v9 216 | strategy: 217 | fail-fast: false 218 | matrix: 219 | cfg: 220 | - { comp: clang , arch: x86, mode: Debug } 221 | - { comp: clang , arch: x86, mode: Release } 222 | steps: 223 | - name: Fetch current branch 224 | uses: actions/checkout@v4.1.1 225 | - name: Running CMake for ${{ matrix.cfg.comp }} in ${{ matrix.cfg.mode }} mode 226 | run: | 227 | mkdir build && cd build 228 | cmake .. -G Ninja -DCMAKE_BUILD_TYPE="${{ matrix.cfg.mode }}" \ 229 | -DCMAKE_TOOLCHAIN_FILE=../test/toolchain/${{ matrix.cfg.comp }}.${{ matrix.cfg.arch }}.cmake 230 | - name: Compiling Unit Tests 231 | run: cd build && ninja spy-test -j 2 232 | - name: Running Unit Tests 233 | run: cd build && ctest --verbose --output-on-failure -j 2 234 | 235 | ################################################################################################## 236 | ## gcc targets 237 | ################################################################################################## 238 | gcc: 239 | runs-on: ubuntu-latest 240 | container: 241 | image: ghcr.io/jfalcou/compilers:v9 242 | strategy: 243 | fail-fast: false 244 | matrix: 245 | cfg: 246 | - { comp: gcc , arch: x86 , opts: , mode: Debug } 247 | - { comp: gcc , arch: x86 , opts: , mode: Release } 248 | - { comp: gcc , arch: aarch64 , opts: -Wno-psabi, mode: Debug } 249 | - { comp: gcc , arch: aarch64 , opts: -Wno-psabi, mode: Release } 250 | - { comp: gcc , arch: aarch64.sve , opts: -Wno-psabi, mode: Debug } 251 | - { comp: gcc , arch: aarch64.sve , opts: -Wno-psabi, mode: Release } 252 | - { comp: gcc , arch: aarch64.sve2, opts: -Wno-psabi, mode: Debug } 253 | - { comp: gcc , arch: aarch64.sve2, opts: -Wno-psabi, mode: Release } 254 | - { comp: gcc , arch: ppc64 , opts: -Wno-psabi, mode: Debug } 255 | - { comp: gcc , arch: ppc64 , opts: -Wno-psabi, mode: Release } 256 | steps: 257 | - name: Fetch current branch 258 | uses: actions/checkout@v4.1.1 259 | - name: Running CMake for ${{ matrix.cfg.comp }} in ${{ matrix.cfg.mode }} mode 260 | run: | 261 | mkdir build && cd build 262 | cmake .. -G Ninja -DCMAKE_BUILD_TYPE="${{ matrix.cfg.mode }}" \ 263 | -DCMAKE_TOOLCHAIN_FILE=../test/toolchain/${{ matrix.cfg.comp }}.${{ matrix.cfg.arch }}.cmake 264 | - name: Compile Unit Tests 265 | run: cd build && ninja spy-test -j 2 266 | - name: Running Unit Tests 267 | run: cd build && ctest --verbose --output-on-failure -j 2 268 | -------------------------------------------------------------------------------- /include/spy/simd.hpp: -------------------------------------------------------------------------------- 1 | //================================================================================================== 2 | /* 3 | SPY - C++ Informations Broker 4 | Copyright : SPY Project Contributors 5 | SPDX-License-Identifier: BSL-1.0 6 | */ 7 | //================================================================================================== 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace spy::_ 17 | { 18 | enum class simd_isa 19 | { 20 | undefined_ = -1, 21 | x86_ = 1000, 22 | ppc_ = 2000, 23 | arm_ = 3000, 24 | arm_sve_ = 3500, 25 | wasm_ = 4000, 26 | riscv_ = 5000 27 | }; 28 | 29 | enum class simd_version 30 | { 31 | undefined_ = -1, 32 | sse1_ = 1110, 33 | sse2_ = 1120, 34 | sse3_ = 1130, 35 | ssse3_ = 1131, 36 | sse41_ = 1141, 37 | sse42_ = 1142, 38 | avx_ = 1201, 39 | avx2_ = 1202, 40 | avx512_ = 1300, 41 | vmx_ = 2000, 42 | vmx_2_03_ = 2203, 43 | vmx_2_05_ = 2205, 44 | vmx_2_06_ = 2206, 45 | vmx_2_07_ = 2207, 46 | vmx_3_00_ = 2300, 47 | vmx_3_01_ = 2301, 48 | vsx_ = 3000, 49 | vsx_2_06_ = 3206, 50 | vsx_2_07_ = 3207, 51 | vsx_3_00_ = 3300, 52 | vsx_3_01_ = 3301, 53 | neon_ = 4001, 54 | asimd_ = 4002, 55 | sve_ = 5000, 56 | fixed_sve_ = 5100, 57 | sve2_ = 5500, 58 | fixed_sve2_ = 5600, 59 | simd128_ = 6000, 60 | rvv_ = 7000, 61 | fixed_rvv_ = 7500 62 | }; 63 | 64 | template struct simd_info 65 | { 66 | static constexpr auto isa = InsSetArch; 67 | static constexpr auto version = Version; 68 | 69 | static constexpr int width = []() { 70 | if constexpr (Version == simd_version::simd128_ || 71 | (Version >= simd_version::sse1_ && Version <= simd_version::sse42_) || 72 | Version == simd_version::neon_ || Version == simd_version::asimd_ || 73 | (Version >= simd_version::vmx_2_03_ && Version <= simd_version::vsx_3_01_)) 74 | return 128; 75 | else if constexpr (Version == simd_version::avx_ || Version == simd_version::avx2_) return 256; 76 | else if constexpr (Version == simd_version::avx512_) return 512; 77 | else if constexpr (Version == simd_version::rvv_) return -1; 78 | else if constexpr (Version == simd_version::fixed_rvv_) 79 | { 80 | #if defined(__riscv_v_fixed_vlen) 81 | return __riscv_v_fixed_vlen; 82 | #else 83 | return -1; 84 | #endif 85 | } 86 | else if constexpr (Version == simd_version::sve_ || Version == simd_version::sve2_) { return -1; } 87 | else if constexpr (Version == simd_version::fixed_sve_ || Version == simd_version::fixed_sve2_) 88 | { 89 | #if defined(__ARM_FEATURE_SVE_BITS) 90 | return __ARM_FEATURE_SVE_BITS; 91 | #else 92 | return -1; 93 | #endif 94 | } 95 | else return -1; 96 | }(); 97 | 98 | static constexpr bool has_fixed_cardinal() { return width != -1; } 99 | 100 | template<_::stream OS> friend auto& operator<<(OS& os, simd_info const&) 101 | { 102 | if constexpr (Version == simd_version::simd128_) os << "WASM SIMD128"; 103 | else if constexpr (Version == simd_version::sse1_) os << "X86 SSE"; 104 | else if constexpr (Version == simd_version::sse2_) os << "X86 SSE2"; 105 | else if constexpr (Version == simd_version::sse3_) os << "X86 SSE3"; 106 | else if constexpr (Version == simd_version::ssse3_) os << "X86 SSSE3"; 107 | else if constexpr (Version == simd_version::sse41_) os << "X86 SSE4.1"; 108 | else if constexpr (Version == simd_version::sse42_) os << "X86 SSE4.2"; 109 | else if constexpr (Version == simd_version::avx_) os << "X86 AVX"; 110 | else if constexpr (Version == simd_version::avx2_) os << "X86 AVX2"; 111 | else if constexpr (Version == simd_version::avx512_) os << "X86 AVX512"; 112 | else if constexpr (Version >= simd_version::vmx_2_03_ && Version <= simd_version::vmx_3_01_) 113 | { 114 | constexpr auto v = static_cast(Version); 115 | os << "PPC VMX with ISA v" << ((v - 2000) / 100.); 116 | } 117 | else if constexpr (Version >= simd_version::vsx_2_06_ && Version <= simd_version::vsx_3_01_) 118 | { 119 | constexpr auto v = static_cast(Version); 120 | os << "PPC VSX with ISA v" << ((v - 3000) / 100.); 121 | } 122 | else if constexpr (Version == simd_version::neon_) os << "ARM NEON"; 123 | else if constexpr (Version == simd_version::asimd_) os << "ARM ASIMD"; 124 | else if constexpr (Version == simd_version::sve_) os << "ARM SVE (dyn.)"; 125 | else if constexpr (Version == simd_version::fixed_sve_) os << "ARM SVE (" << simd_info::width << " bits)"; 126 | else if constexpr (Version == simd_version::sve2_) os << "ARM SVE2 (dyn.)"; 127 | else if constexpr (Version == simd_version::fixed_sve2_) os << "ARM SVE2 (" << simd_info::width << " bits)"; 128 | else if constexpr (Version == simd_version::rvv_) os << "RISC-V RVV (dyn.)"; 129 | else if constexpr (Version == simd_version::fixed_rvv_) os << "RISC-V RVV (" << simd_info::width << " bits)"; 130 | else return os << "Undefined SIMD instructions set"; 131 | 132 | if constexpr (spy::supports::fma_) os << " (with FMA3 support)"; 133 | if constexpr (spy::supports::fma4_) os << " (with FMA4 support)"; 134 | if constexpr (spy::supports::xop_) os << " (with XOP support)"; 135 | 136 | return os; 137 | } 138 | }; 139 | 140 | template 141 | constexpr bool operator==(simd_info, simd_info) noexcept 142 | { 143 | if constexpr (V1 != simd_version::undefined_ && V2 != simd_version::undefined_) return (I1 == I2) && (V1 == V2); 144 | else return I1 == I2; 145 | } 146 | 147 | template 148 | constexpr std::partial_ordering operator<=>(simd_info, simd_info) noexcept 149 | { 150 | if constexpr (I1 != I2) return std::partial_ordering::unordered; 151 | else return static_cast(V1) <=> static_cast(V2); 152 | } 153 | } 154 | 155 | namespace spy 156 | { 157 | //================================================================================================ 158 | //! @ingroup api 159 | //! @brief SIMD extensions set reporting value 160 | //! 161 | //! @groupheader{SIMD Instructions Sets} 162 | //! SIMD extensions set detection is made so that one can ask if the current SIMD extension is exactly, 163 | //! below or above a given reference instruction set. Detectable instructions sets depends on SIMD 164 | //! hardware vendor 165 | //! 166 | //! | Architecture | Supported SIMD instructions sets | 167 | //! | ----------------- | --------------------------------------------------------------------------------------- | 168 | //! | **X86 SSE** | `spy::sse1_`, `spy::sse2_`, `spy::sse3_`, `spy::ssse3_`, `spy::sse41_`, `spy::sse42_` | 169 | //! | **X86 AVX** | `spy::avx_`, `spy::avx2_`, `spy::avx512_` | 170 | //! | **Power PC VMX** | `spy::vmx_`, `spy::vmx_2_03_`, `spy::vmx_2_05_`, `spy::vmx_2_06_`, `spy::vmx_2_07_`, 171 | //! `spy::vmx_3_00_`, `spy::vmx_3_01_` | | **Power PC VSX** | `spy::vsx_`, `spy::vsx_2_06_`, `spy::vsx_2_07_`, 172 | //! `spy::vsx_3_00_`, `spy::vsx_3_01_` | | **ARM NEON** | `spy::neon_`, `spy::asimd_` | | **ARM SVE** | 173 | //! `spy::sve_`,`spy::sve128_`, `spy::sve256_`, `spy::sve512_`, `spy::sve1024_` | | **WASM** | 174 | //! `spy::simd128_` | | **RISC-V** | 175 | //! `spy::rvv_`` | 176 | //! 177 | //! Complete set of comparison operators is provided for those sets. Order of instructions sets 178 | //! are built so that if an instructions set supersedes another, it is considered greater than. For 179 | //! example, `spy::avx_` is greater than `spy::sse41_` as the former is a super-set of the later. 180 | //! Comparing SIMD descriptors across architecture is undefined behavior. 181 | //! 182 | //! Moreover, the `spy::simd_instruction_set` object exposes a constexpr `width` static field that 183 | //! contains the size in bits of the current SIMD instructions set registers. 184 | //! 185 | //! @subgroupheader{Example - SIMD Instructions Sets} 186 | //! @godbolt{samples/simd.cpp} 187 | //! 188 | //! @groupheader{SIMD Architectures} 189 | //! 190 | //! One can also simply asks if a given family of instructions set is available. 191 | //! 192 | //! | Architecture | Generic indicator | 193 | //! | ------------- | --------------------| 194 | //! | **X86** | `spy::x86_simd_` | 195 | //! | **Power PC** | `spy::ppc_simd_` | 196 | //! | **ARM** | `spy::arm_simd_` | 197 | //! | **WASM** | `spy::wasm_simd_` | 198 | //! | **RISC-V** | `spy::riscv_simd_` | 199 | //! 200 | //! @subgroupheader{Example - SIMD Architectures} 201 | //! @godbolt{samples/simd-arch.cpp} 202 | //! 203 | //! @groupheader{Supplemental Instructions sets} 204 | //! 205 | //! Some SIMD instructions set provides supplemental instructions on top of existing system. 206 | //! Those supplemental instruction set can be checked using the `spy::supports` namespace. 207 | //! 208 | //! | Architecture | Supported SIMD instructions sets | 209 | //! | ------------- | ------------------------------------------------------------------------------------| 210 | //! | X86 AVX | `xop_`, `fma_`, `fma4_` | 211 | //! | X86 AVX512 | `bw_`, `cd_`, `dq_`, `er_`, `ifma_`, `pf_`, `vl_`, `popcntdq_` | 212 | //! | | `_4fmaps_`, `vnniw_`, `vbmi_`, `bf16_`,`bitalg_`, `vbmi2_`, `vnni_`, `vpintersect_` | 213 | //! 214 | //! @subgroupheader{Example - SIMD Architectures} 215 | //! @godbolt{samples/simd-additional.cpp} 216 | //! 217 | //================================================================================================ 218 | #if defined(SPY_SIMD_DETECTED) 219 | constexpr inline auto simd_instruction_set = _::simd_info{}; 220 | #else 221 | constexpr inline auto simd_instruction_set = _::simd_info<>{}; 222 | #endif 223 | 224 | //================================================================================================ 225 | // Available SIMD instructions set 226 | //================================================================================================ 227 | constexpr inline auto undefined_simd_ = _::simd_info<>{}; 228 | 229 | template<_::simd_version V = _::simd_version::undefined_> using wasm_simd_info = _::simd_info<_::simd_isa::wasm_, V>; 230 | 231 | constexpr inline auto wasm_simd_ = wasm_simd_info<>{}; 232 | constexpr inline auto simd128_ = wasm_simd_info<_::simd_version::simd128_>{}; 233 | 234 | template<_::simd_version V = _::simd_version::undefined_> using x86_simd_info = _::simd_info<_::simd_isa::x86_, V>; 235 | 236 | constexpr inline auto x86_simd_ = x86_simd_info<>{}; 237 | constexpr inline auto sse1_ = x86_simd_info<_::simd_version::sse1_>{}; 238 | constexpr inline auto sse2_ = x86_simd_info<_::simd_version::sse2_>{}; 239 | constexpr inline auto sse3_ = x86_simd_info<_::simd_version::sse3_>{}; 240 | constexpr inline auto ssse3_ = x86_simd_info<_::simd_version::ssse3_>{}; 241 | constexpr inline auto sse41_ = x86_simd_info<_::simd_version::sse41_>{}; 242 | constexpr inline auto sse42_ = x86_simd_info<_::simd_version::sse42_>{}; 243 | constexpr inline auto avx_ = x86_simd_info<_::simd_version::avx_>{}; 244 | constexpr inline auto avx2_ = x86_simd_info<_::simd_version::avx2_>{}; 245 | constexpr inline auto avx512_ = x86_simd_info<_::simd_version::avx512_>{}; 246 | 247 | template<_::simd_version V = _::simd_version::undefined_> using ppc_simd_info = _::simd_info<_::simd_isa::ppc_, V>; 248 | 249 | constexpr inline auto ppc_simd_ = ppc_simd_info<>{}; 250 | constexpr inline auto vmx_ = ppc_simd_info<_::simd_version::vmx_>{}; 251 | constexpr inline auto vmx_2_03_ = ppc_simd_info<_::simd_version::vmx_2_03_>{}; 252 | constexpr inline auto vmx_2_05_ = ppc_simd_info<_::simd_version::vmx_2_05_>{}; 253 | constexpr inline auto vmx_2_06_ = ppc_simd_info<_::simd_version::vmx_2_06_>{}; 254 | constexpr inline auto vmx_2_07_ = ppc_simd_info<_::simd_version::vmx_2_07_>{}; 255 | constexpr inline auto vmx_3_00_ = ppc_simd_info<_::simd_version::vmx_3_00_>{}; 256 | constexpr inline auto vmx_3_01_ = ppc_simd_info<_::simd_version::vmx_3_01_>{}; 257 | 258 | constexpr inline auto vsx_ = ppc_simd_info<_::simd_version::vsx_>{}; 259 | constexpr inline auto vsx_2_06_ = ppc_simd_info<_::simd_version::vsx_2_06_>{}; 260 | constexpr inline auto vsx_2_07_ = ppc_simd_info<_::simd_version::vsx_2_07_>{}; 261 | constexpr inline auto vsx_3_00_ = ppc_simd_info<_::simd_version::vsx_3_00_>{}; 262 | constexpr inline auto vsx_3_01_ = ppc_simd_info<_::simd_version::vsx_3_01_>{}; 263 | 264 | template<_::simd_version V = _::simd_version::undefined_> using arm_simd_info = _::simd_info<_::simd_isa::arm_, V>; 265 | 266 | template<_::simd_version V = _::simd_version::undefined_> 267 | using sve_simd_info = _::simd_info<_::simd_isa::arm_sve_, V>; 268 | 269 | constexpr inline auto arm_simd_ = arm_simd_info<>{}; 270 | constexpr inline auto neon_ = arm_simd_info<_::simd_version::neon_>{}; 271 | constexpr inline auto asimd_ = arm_simd_info<_::simd_version::asimd_>{}; 272 | constexpr inline auto sve_ = sve_simd_info<_::simd_version::sve_>{}; 273 | constexpr inline auto fixed_sve_ = sve_simd_info<_::simd_version::fixed_sve_>{}; 274 | constexpr inline auto sve2_ = sve_simd_info<_::simd_version::sve2_>{}; 275 | constexpr inline auto fixed_sve2_ = sve_simd_info<_::simd_version::fixed_sve2_>{}; 276 | 277 | template<_::simd_version V = _::simd_version::undefined_> 278 | using riscv_simd_info = _::simd_info<_::simd_isa::riscv_, V>; 279 | constexpr inline auto riscv_simd_ = riscv_simd_info<>{}; 280 | constexpr inline auto rvv_ = riscv_simd_info<_::simd_version::rvv_>{}; 281 | constexpr inline auto fixed_rvv_ = riscv_simd_info<_::simd_version::fixed_rvv_>{}; 282 | } 283 | --------------------------------------------------------------------------------