diff --git a/.gitignore b/.gitignore index 182d36594..c9548fdbb 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ jj.ijs *.sln* *.vcxproj* !*.template +.vs/ # mac .DS_Store @@ -58,6 +59,8 @@ release /test/temp.ijs # build folders +out/ +build/ bin/ make2/ jlibrary/addons/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..447b2ae58 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,94 @@ +cmake_minimum_required(VERSION 3.17) + +get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(is_multi_config) + set(CMAKE_CONFIGURATION_TYPES Debug Release CACHE STRING + "Semicolon separated list of supported configuration types") + mark_as_advanced(CMAKE_CONFIGURATION_TYPES) +elseif(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_C_FLAGS) + message(WARNING "No CMAKE_BUILD_TYPE is selected") +endif() + +project(j) +enable_language(C CXX ASM) + +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + +include(CTest) +include(OptimizeForArchitecture) + +if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(BUILD_SHARED_LIBS ON) +endif() + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_VISIBILITY_PRESET hidden) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_VISIBILITY_PRESET hidden) + +find_package(StandardMathLibrary REQUIRED) +find_package(OpenMP) +find_package(JNI) + +set(TARGET_ARCHITECTURE "skylake" CACHE STRING "CPU architecture") +OptimizeForArchitecture() +add_compile_options("$<$:${Vc_ARCHITECTURE_FLAGS}>") +add_compile_options("$<$:${Vc_ARCHITECTURE_FLAGS}>") + +add_compile_options($<$:-fno-strict-aliasing>) +add_compile_options($<$:-Werror>) +if("${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC") + add_compile_options($<$:/W3>) + add_compile_options($<$:/Zc:strictStrings>) +else() + add_compile_options($<$:-Wextra>) +endif() +add_compile_options($<$:-Wno-unused-parameter>) +add_compile_options($<$:-Wno-unused-value>) +add_compile_options($<$:-Wno-unused-function>) +add_compile_options($<$:-Wno-unused-variable>) +add_compile_options($<$:-Wno-sign-compare>) +add_compile_options($<$:-Wno-cast-function-type>) +add_compile_options($<$:-Wno-clobbered>) +add_compile_options($<$:-Wno-empty-body>) +add_compile_options($<$:-Wno-parentheses>) +add_compile_options($<$:-Wno-pointer-sign>) +add_compile_options($<$:-Wno-format-overflow>) +add_compile_options($<$:-Wno-implicit-fallthrough>) +add_compile_options($<$:-Wno-missing-field-initializers>) +add_compile_options($<$:-Wno-shift-negative-value>) +add_compile_options($<$:-Wuninitialized>) +add_compile_options($<$:-Wno-maybe-uninitialized>) +add_compile_options($<$:-Wno-type-limits>) +add_compile_options($<$:-Wuninitialized>) +add_compile_options($<$:-Wno-sometimes-uninitialized>) +add_compile_options($<$:-Wtautological-constant-out-of-range-compare>) +add_compile_options($<$:-Wno-char-subscripts>) +add_compile_options($<$:-Wno-consumed>) +add_compile_options($<$:-Wno-implicit-float-conversion>) +add_compile_options($<$:-Wno-implicit-int-float-conversion>) +add_compile_options($<$:-Wno-int-in-bool-context>) +add_compile_options($<$:-Wno-string-plus-int>) +add_compile_options($<$:-Wno-missing-braces>) +add_compile_options($<$:-Wno-unknown-pragmas>) +add_compile_options($<$:-Wno-delete-non-abstract-non-virtual-dtor>) + +add_subdirectory(jsrc) +add_subdirectory(sleef) +add_subdirectory(base64) +add_subdirectory(dllsrc) +add_subdirectory(jsrc/openssl/sha) + +if(BUILD_SHARED_LIBS) + set_target_properties(j-openssl-sha j-sleef j-base64 PROPERTIES + POSITION_INDEPENDENT_CODE ON) + add_subdirectory(test) +endif() +target_link_libraries(j PRIVATE j-openssl-sha j-sleef j-base64) +if(WIN32) + target_link_libraries(j PRIVATE j-dll) + target_sources(j PRIVATE dllsrc/jdll.def dllsrc/jdll.rc dllsrc/jdll.tlb) +endif() diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 000000000..f5e73573b --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,28 @@ +{ + "configurations": [ + { + "name": "x64-Clang-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "variables": [] + }, + { + "name": "x64-Clang-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "variables": [] + } + ] +} \ No newline at end of file diff --git a/base64/CMakeLists.txt b/base64/CMakeLists.txt new file mode 100644 index 000000000..eb533dc9c --- /dev/null +++ b/base64/CMakeLists.txt @@ -0,0 +1,21 @@ +add_library(j-base64 OBJECT) +target_compile_definitions(j-base64 PRIVATE HAVE_AVX2=1) +target_sources(j-base64 PRIVATE + include/libbase64.h + lib/arch/avx/codec-avx.c + lib/arch/avx2/codec-avx2.c + lib/arch/generic/codec-generic.c + lib/arch/neon64/codec-neon64.c + lib/arch/sse41/codec-sse41.c + lib/arch/sse42/codec-sse42.c + lib/arch/ssse3/codec-ssse3.c + lib/codecs.h + lib/codec_choose.c + lib/config.h + lib/env.h + lib/lib.c + lib/tables/tables.c + lib/tables/tables.h + lib/tables/table_dec_32bit.h + lib/tables/table_enc_12bit.h +) diff --git a/cmake/AddCompilerFlag.cmake b/cmake/AddCompilerFlag.cmake new file mode 100644 index 000000000..6684fa54a --- /dev/null +++ b/cmake/AddCompilerFlag.cmake @@ -0,0 +1,130 @@ +# - Add a given compiler flag to flags variables. +# AddCompilerFlag( []) +# or +# AddCompilerFlag( [C_FLAGS ] [CXX_FLAGS ] [C_RESULT ] +# [CXX_RESULT ]) + +#============================================================================= +# Copyright 2010-2015 Matthias Kretz +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the names of contributing organizations nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH) +include("${_currentDir}/CheckCCompilerFlag.cmake") +include("${_currentDir}/CheckCXXCompilerFlag.cmake") + +macro(AddCompilerFlag _flag) + string(REGEX REPLACE "[-.+/:= ]" "_" _flag_esc "${_flag}") + + set(_c_flags "CMAKE_C_FLAGS") + set(_cxx_flags "CMAKE_CXX_FLAGS") + set(_c_result tmp) + set(_cxx_result tmp) + if(${ARGC} EQUAL 2) + message(WARNING "Deprecated use of the AddCompilerFlag macro.") + unset(_c_result) + set(_cxx_result ${ARGV1}) + elseif(${ARGC} GREATER 2) + set(state 0) + unset(_c_flags) + unset(_cxx_flags) + unset(_c_result) + unset(_cxx_result) + foreach(_arg ${ARGN}) + if("x${_arg}" STREQUAL "xC_FLAGS") + set(state 1) + if(NOT DEFINED _c_result) + set(_c_result tmp0) + endif() + elseif("x${_arg}" STREQUAL "xCXX_FLAGS") + set(state 2) + if(NOT DEFINED _cxx_result) + set(_cxx_result tmp1) + endif() + elseif("x${_arg}" STREQUAL "xC_RESULT") + set(state 3) + elseif("x${_arg}" STREQUAL "xCXX_RESULT") + set(state 4) + elseif(state EQUAL 1) + set(_c_flags "${_arg}") + elseif(state EQUAL 2) + set(_cxx_flags "${_arg}") + elseif(state EQUAL 3) + set(_c_result "${_arg}") + elseif(state EQUAL 4) + set(_cxx_result "${_arg}") + else() + message(FATAL_ERROR "Syntax error for AddCompilerFlag") + endif() + endforeach() + endif() + + set(_c_code "int main() { return 0; }") + set(_cxx_code "int main() { return 0; }") + if("${_flag}" STREQUAL "-mfma") + # Compiling with FMA3 support may fail only at the assembler level. + # In that case we need to have such an instruction in the test code + set(_c_code "#include + __m128 foo(__m128 x) { return _mm_fmadd_ps(x, x, x); } + int main() { return 0; }") + set(_cxx_code "${_c_code}") + elseif("${_flag}" STREQUAL "-stdlib=libc++") + # Compiling with libc++ not only requires a compiler that understands it, but also + # the libc++ headers itself + set(_cxx_code "#include + #include + int main() { return 0; }") + else() + set(_cxx_code "#include + int main() { return 0; }") + endif() + + if(DEFINED _c_result) + check_c_compiler_flag("${_flag}" check_c_compiler_flag_${_flag_esc} "${_c_code}") + set(${_c_result} ${check_c_compiler_flag_${_flag_esc}}) + endif() + if(DEFINED _cxx_result) + check_cxx_compiler_flag("${_flag}" check_cxx_compiler_flag_${_flag_esc} "${_cxx_code}") + set(${_cxx_result} ${check_cxx_compiler_flag_${_flag_esc}}) + endif() + + macro(my_append _list _flag _special) + if("x${_list}" STREQUAL "x${_special}") + set(${_list} "${${_list}} ${_flag}") + else() + list(APPEND ${_list} "${_flag}") + endif() + endmacro() + + if(check_c_compiler_flag_${_flag_esc} AND DEFINED _c_flags) + my_append(${_c_flags} "${_flag}" CMAKE_C_FLAGS) + endif() + if(check_cxx_compiler_flag_${_flag_esc} AND DEFINED _cxx_flags) + my_append(${_cxx_flags} "${_flag}" CMAKE_CXX_FLAGS) + endif() +endmacro(AddCompilerFlag) diff --git a/cmake/CheckCCompilerFlag.cmake b/cmake/CheckCCompilerFlag.cmake new file mode 100644 index 000000000..07ec156e0 --- /dev/null +++ b/cmake/CheckCCompilerFlag.cmake @@ -0,0 +1,73 @@ +# - Check whether the C compiler supports a given flag. +# CHECK_C_COMPILER_FLAG( ) +# - the compiler flag +# - variable to store the result +# This internally calls the check_c_source_compiles macro. +# See help for CheckCSourceCompiles for a listing of variables +# that can modify the build. + +#============================================================================= +# Copyright 2006-2009 Kitware, Inc. +# Copyright 2006 Alexander Neundorf +# Copyright 2011-2013 Matthias Kretz +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * The names of Kitware, Inc., the Insight Consortium, or the names of +# any consortium members, or of any contributors, may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +INCLUDE(CheckCSourceCompiles) + +MACRO (CHECK_C_COMPILER_FLAG _FLAG _RESULT) + SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") + SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") + if(${ARGC} GREATER 2) + SET(TEST_SOURCE "${ARGV2}") + else() + SET(TEST_SOURCE "int main() { return 0;}") + endif() + CHECK_C_SOURCE_COMPILES("${TEST_SOURCE}" ${_RESULT} + # Some compilers do not fail with a bad flag + FAIL_REGEX "error: bad value (.*) for .* switch" # GNU + FAIL_REGEX "argument unused during compilation" # clang + FAIL_REGEX "is valid for .* but not for C" # GNU + FAIL_REGEX "unrecognized .*option" # GNU + FAIL_REGEX "ignored for target" # GNU + FAIL_REGEX "ignoring unknown option" # MSVC + FAIL_REGEX "warning D9002" # MSVC + FAIL_REGEX "[Uu]nknown option" # HP + FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro + FAIL_REGEX "command option .* is not recognized" # XL + FAIL_REGEX "WARNING: unknown flag:" # Open64 + FAIL_REGEX "command line error" # ICC + FAIL_REGEX "command line warning" # ICC + FAIL_REGEX "#10236:" # ICC: File not found + FAIL_REGEX " #10159: " # ICC + FAIL_REGEX " #10353: " # ICC: option '-mfma' ignored, suggest using '-march=core-avx2' + ) + SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") +ENDMACRO (CHECK_C_COMPILER_FLAG) + diff --git a/cmake/CheckCXXCompilerFlag.cmake b/cmake/CheckCXXCompilerFlag.cmake new file mode 100644 index 000000000..e3b0188a4 --- /dev/null +++ b/cmake/CheckCXXCompilerFlag.cmake @@ -0,0 +1,73 @@ +# - Check whether the CXX compiler supports a given flag. +# CHECK_CXX_COMPILER_FLAG( ) +# - the compiler flag +# - variable to store the result +# This internally calls the check_cxx_source_compiles macro. See help +# for CheckCXXSourceCompiles for a listing of variables that can +# modify the build. + +#============================================================================= +# Copyright 2006-2009 Kitware, Inc. +# Copyright 2006 Alexander Neundorf +# Copyright 2011-2013 Matthias Kretz +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * The names of Kitware, Inc., the Insight Consortium, or the names of +# any consortium members, or of any contributors, may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +INCLUDE(CheckCXXSourceCompiles) + +MACRO (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT) + SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") + SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") + if(${ARGC} GREATER 2) + SET(TEST_SOURCE "${ARGV2}") + else() + SET(TEST_SOURCE "int main() { return 0;}") + endif() + CHECK_CXX_SOURCE_COMPILES("${TEST_SOURCE}" ${_RESULT} + # Some compilers do not fail with a bad flag + FAIL_REGEX "error: bad value (.*) for .* switch" # GNU + FAIL_REGEX "argument unused during compilation" # clang + FAIL_REGEX "is valid for .* but not for C\\\\+\\\\+" # GNU + FAIL_REGEX "unrecognized .*option" # GNU + FAIL_REGEX "ignored for target" # GNU + FAIL_REGEX "ignoring unknown option" # MSVC + FAIL_REGEX "warning D9002" # MSVC + FAIL_REGEX "[Uu]nknown option" # HP + FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro + FAIL_REGEX "command option .* is not recognized" # XL + FAIL_REGEX "WARNING: unknown flag:" # Open64 + FAIL_REGEX "command line error" # ICC + FAIL_REGEX "command line warning" # ICC + FAIL_REGEX "#10236:" # ICC: File not found + FAIL_REGEX " #10159: " # ICC + FAIL_REGEX " #10353: " # ICC: option '-mfma' ignored, suggest using '-march=core-avx2' + ) + SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") +ENDMACRO (CHECK_CXX_COMPILER_FLAG) + diff --git a/cmake/FindStandardMathLibrary.cmake b/cmake/FindStandardMathLibrary.cmake new file mode 100644 index 000000000..c01b1df13 --- /dev/null +++ b/cmake/FindStandardMathLibrary.cmake @@ -0,0 +1,68 @@ +# - Try to find how to link to the standard math library, if anything at all is needed to do. +# On most platforms this is automatic, but for example it's not automatic on QNX. +# +# Once done this will define +# +# STANDARD_MATH_LIBRARY_FOUND - we found how to successfully link to the standard math library +# STANDARD_MATH_LIBRARY - the name of the standard library that one has to link to. +# -- this will be left empty if it's automatic (most platforms). +# -- this will be set to "m" on platforms where one must explicitly +# pass the "-lm" linker flag. +# +# Copyright (c) 2010 Benoit Jacob +# 2020 Susi Lehtola +# Redistribution and use is allowed according to the terms of the 2-clause BSD license. + + +include(CheckCSourceCompiles) + +# a little test program for c math functions. + +# We read in the arguments from standard input to avoid the compiler optimizing away the calls +set(find_standard_math_library_test_program +" +#include +int main(int argc, char **argv){ +return fetestexcept(argc); +}") + +# first try compiling/linking the test program without any linker flags + +set(CMAKE_REQUIRED_FLAGS "") +set(CMAKE_REQUIRED_LIBRARIES "") +CHECK_C_SOURCE_COMPILES( + "${find_standard_math_library_test_program}" + standard_math_library_linked_to_automatically +) + +if(standard_math_library_linked_to_automatically) + + # the test program linked successfully without any linker flag. + set(STANDARD_MATH_LIBRARY "") + set(STANDARD_MATH_LIBRARY_FOUND TRUE) + +else() + + # the test program did not link successfully without any linker flag. + # This is a very uncommon case that so far we only saw on QNX. The next try is the + # standard name 'm' for the standard math library. + + set(CMAKE_REQUIRED_LIBRARIES "m") + CHECK_C_SOURCE_COMPILES( + "${find_standard_math_library_test_program}" + standard_math_library_linked_to_as_m) + + if(standard_math_library_linked_to_as_m) + + # the test program linked successfully when linking to the 'm' library + set(STANDARD_MATH_LIBRARY "m") + set(STANDARD_MATH_LIBRARY_FOUND TRUE) + + else() + + # the test program still doesn't link successfully + set(STANDARD_MATH_LIBRARY_FOUND FALSE) + + endif() + +endif() diff --git a/cmake/OptimizeForArchitecture.cmake b/cmake/OptimizeForArchitecture.cmake new file mode 100644 index 000000000..075956c2e --- /dev/null +++ b/cmake/OptimizeForArchitecture.cmake @@ -0,0 +1,581 @@ +# Determine the host CPU feature set and determine the best set of compiler +# flags to enable all supported SIMD relevant features. Alternatively, the +# target CPU can be explicitly selected (for generating more generic binaries +# or for targeting a different system). +# Compilers provide e.g. the -march=native flag to achieve a similar result. +# This fails to address the need for building for a different microarchitecture +# than the current host. +# The script tries to deduce all settings from the model and family numbers of +# the CPU instead of reading the CPUID flags from e.g. /proc/cpuinfo. This makes +# the detection more independent from the CPUID code in the kernel (e.g. avx2 is +# not listed on older kernels). +# +# Usage: +# OptimizeForArchitecture() +# If either of Vc_SSE_INTRINSICS_BROKEN, Vc_AVX_INTRINSICS_BROKEN, +# Vc_AVX2_INTRINSICS_BROKEN is defined and set, the OptimizeForArchitecture +# macro will consequently disable the relevant features via compiler flags. + +#============================================================================= +# Copyright 2010-2016 Matthias Kretz +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the names of contributing organizations nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH) +include("${_currentDir}/AddCompilerFlag.cmake") +include(CheckIncludeFileCXX) + +macro(_my_find _list _value _ret) + list(FIND ${_list} "${_value}" _found) + if(_found EQUAL -1) + set(${_ret} FALSE) + else(_found EQUAL -1) + set(${_ret} TRUE) + endif(_found EQUAL -1) +endmacro(_my_find) + +macro(AutodetectHostArchitecture) + set(TARGET_ARCHITECTURE "generic") + set(Vc_ARCHITECTURE_FLAGS) + set(_vendor_id) + set(_cpu_family) + set(_cpu_model) + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + file(READ "/proc/cpuinfo" _cpuinfo) + string(REGEX REPLACE ".*vendor_id[ \t]*:[ \t]+([a-zA-Z0-9_-]+).*" "\\1" _vendor_id "${_cpuinfo}") + string(REGEX REPLACE ".*cpu family[ \t]*:[ \t]+([a-zA-Z0-9_-]+).*" "\\1" _cpu_family "${_cpuinfo}") + string(REGEX REPLACE ".*model[ \t]*:[ \t]+([a-zA-Z0-9_-]+).*" "\\1" _cpu_model "${_cpuinfo}") + string(REGEX REPLACE ".*flags[ \t]*:[ \t]+([^\n]+).*" "\\1" _cpu_flags "${_cpuinfo}") + elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + exec_program("/usr/sbin/sysctl -n machdep.cpu.vendor machdep.cpu.model machdep.cpu.family machdep.cpu.features" OUTPUT_VARIABLE _sysctl_output_string) + string(REPLACE "\n" ";" _sysctl_output ${_sysctl_output_string}) + list(GET _sysctl_output 0 _vendor_id) + list(GET _sysctl_output 1 _cpu_model) + list(GET _sysctl_output 2 _cpu_family) + list(GET _sysctl_output 3 _cpu_flags) + + string(TOLOWER "${_cpu_flags}" _cpu_flags) + string(REPLACE "." "_" _cpu_flags "${_cpu_flags}") + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + get_filename_component(_vendor_id "[HKEY_LOCAL_MACHINE\\Hardware\\Description\\System\\CentralProcessor\\0;VendorIdentifier]" NAME CACHE) + get_filename_component(_cpu_id "[HKEY_LOCAL_MACHINE\\Hardware\\Description\\System\\CentralProcessor\\0;Identifier]" NAME CACHE) + mark_as_advanced(_vendor_id _cpu_id) + string(REGEX REPLACE ".* Family ([0-9]+) .*" "\\1" _cpu_family "${_cpu_id}") + string(REGEX REPLACE ".* Model ([0-9]+) .*" "\\1" _cpu_model "${_cpu_id}") + endif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if(_vendor_id STREQUAL "GenuineIntel") + if(_cpu_family EQUAL 6) + # taken from the Intel ORM + # http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html + # CPUID Signature Values of Of Recent Intel Microarchitectures + # 4E 5E | Skylake microarchitecture + # 3D 47 56 | Broadwell microarchitecture + # 3C 45 46 3F | Haswell microarchitecture + # 3A 3E | Ivy Bridge microarchitecture + # 2A 2D | Sandy Bridge microarchitecture + # 25 2C 2F | Intel microarchitecture Westmere + # 1A 1E 1F 2E | Intel microarchitecture Nehalem + # 17 1D | Enhanced Intel Core microarchitecture + # 0F | Intel Core microarchitecture + # + # Intel SDM Vol. 3C 35-1 / December 2016: + # 57 | Xeon Phi 3200, 5200, 7200 [Knights Landing] + # 85 | Future Xeon Phi + # 8E 9E | 7th gen. Core [Kaby Lake] + # 55 | Future Xeon [Skylake w/ AVX512] + # 4E 5E | 6th gen. Core / E3 v5 [Skylake w/o AVX512] + # 56 | Xeon D-1500 [Broadwell] + # 4F | Xeon E5 v4, E7 v4, i7-69xx [Broadwell] + # 47 | 5th gen. Core / Xeon E3 v4 [Broadwell] + # 3D | M-5xxx / 5th gen. [Broadwell] + # 3F | Xeon E5 v3, E7 v3, i7-59xx [Haswell-E] + # 3C 45 46 | 4th gen. Core, Xeon E3 v3 [Haswell] + # 3E | Xeon E5 v2, E7 v2, i7-49xx [Ivy Bridge-E] + # 3A | 3rd gen. Core, Xeon E3 v2 [Ivy Bridge] + # 2D | Xeon E5, i7-39xx [Sandy Bridge] + # 2F | Xeon E7 + # 2A | Xeon E3, 2nd gen. Core [Sandy Bridge] + # 2E | Xeon 7500, 6500 series + # 25 2C | Xeon 3600, 5600 series, Core i7, i5 and i3 + # + # Values from the Intel SDE: + # 5C | Goldmont + # 5A | Silvermont + # 57 | Knights Landing + # 66 | Cannonlake + # 55 | Skylake Server + # 4E | Skylake Client + # 3C | Broadwell (likely a bug in the SDE) + # 3C | Haswell + if(_cpu_model EQUAL 87) # 57 + set(TARGET_ARCHITECTURE "knl") # Knights Landing + elseif(_cpu_model EQUAL 92) + set(TARGET_ARCHITECTURE "goldmont") + elseif(_cpu_model EQUAL 90 OR _cpu_model EQUAL 76) + set(TARGET_ARCHITECTURE "silvermont") + elseif(_cpu_model EQUAL 102) + set(TARGET_ARCHITECTURE "cannonlake") + elseif(_cpu_model EQUAL 142 OR _cpu_model EQUAL 158) # 8E, 9E + set(TARGET_ARCHITECTURE "kaby-lake") + elseif(_cpu_model EQUAL 85) # 55 + set(TARGET_ARCHITECTURE "skylake-avx512") + elseif(_cpu_model EQUAL 78 OR _cpu_model EQUAL 94) # 4E, 5E + set(TARGET_ARCHITECTURE "skylake") + elseif(_cpu_model EQUAL 61 OR _cpu_model EQUAL 71 OR _cpu_model EQUAL 79 OR _cpu_model EQUAL 86) # 3D, 47, 4F, 56 + set(TARGET_ARCHITECTURE "broadwell") + elseif(_cpu_model EQUAL 60 OR _cpu_model EQUAL 69 OR _cpu_model EQUAL 70 OR _cpu_model EQUAL 63) + set(TARGET_ARCHITECTURE "haswell") + elseif(_cpu_model EQUAL 58 OR _cpu_model EQUAL 62) + set(TARGET_ARCHITECTURE "ivy-bridge") + elseif(_cpu_model EQUAL 42 OR _cpu_model EQUAL 45) + set(TARGET_ARCHITECTURE "sandy-bridge") + elseif(_cpu_model EQUAL 37 OR _cpu_model EQUAL 44 OR _cpu_model EQUAL 47) + set(TARGET_ARCHITECTURE "westmere") + elseif(_cpu_model EQUAL 26 OR _cpu_model EQUAL 30 OR _cpu_model EQUAL 31 OR _cpu_model EQUAL 46) + set(TARGET_ARCHITECTURE "nehalem") + elseif(_cpu_model EQUAL 23 OR _cpu_model EQUAL 29) + set(TARGET_ARCHITECTURE "penryn") + elseif(_cpu_model EQUAL 15) + set(TARGET_ARCHITECTURE "merom") + elseif(_cpu_model EQUAL 28) + set(TARGET_ARCHITECTURE "atom") + elseif(_cpu_model EQUAL 14) + set(TARGET_ARCHITECTURE "core") + elseif(_cpu_model LESS 14) + message(WARNING "Your CPU (family ${_cpu_family}, model ${_cpu_model}) is not known. Auto-detection of optimization flags failed and will use the generic CPU settings with SSE2.") + set(TARGET_ARCHITECTURE "generic") + else() + message(WARNING "Your CPU (family ${_cpu_family}, model ${_cpu_model}) is not known. Auto-detection of optimization flags failed and will use the 65nm Core 2 CPU settings.") + set(TARGET_ARCHITECTURE "merom") + endif() + elseif(_cpu_family EQUAL 7) # Itanium (not supported) + message(WARNING "Your CPU (Itanium: family ${_cpu_family}, model ${_cpu_model}) is not supported by OptimizeForArchitecture.cmake.") + elseif(_cpu_family EQUAL 15) # NetBurst + list(APPEND _available_vector_units_list "sse" "sse2") + if(_cpu_model GREATER 2) # Not sure whether this must be 3 or even 4 instead + list(APPEND _available_vector_units_list "sse" "sse2" "sse3") + endif(_cpu_model GREATER 2) + endif(_cpu_family EQUAL 6) + elseif(_vendor_id STREQUAL "AuthenticAMD") + if(_cpu_family EQUAL 23) + set(TARGET_ARCHITECTURE "zen") + elseif(_cpu_family EQUAL 22) # 16h + set(TARGET_ARCHITECTURE "AMD 16h") + elseif(_cpu_family EQUAL 21) # 15h + if(_cpu_model LESS 2) + set(TARGET_ARCHITECTURE "bulldozer") + else() + set(TARGET_ARCHITECTURE "piledriver") + endif() + elseif(_cpu_family EQUAL 20) # 14h + set(TARGET_ARCHITECTURE "AMD 14h") + elseif(_cpu_family EQUAL 18) # 12h + elseif(_cpu_family EQUAL 16) # 10h + set(TARGET_ARCHITECTURE "barcelona") + elseif(_cpu_family EQUAL 15) + set(TARGET_ARCHITECTURE "k8") + if(_cpu_model GREATER 64) # I don't know the right number to put here. This is just a guess from the hardware I have access to + set(TARGET_ARCHITECTURE "k8-sse3") + endif(_cpu_model GREATER 64) + endif() + endif(_vendor_id STREQUAL "GenuineIntel") +endmacro() + +macro(OptimizeForArchitecture) + if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(x86|AMD64)") + OptimizeForArchitectureX86() + else() + message(STATUS "No support for auto-detection of the target instruction set/extension") + set(TARGET_ARCHITECTURE "unused" CACHE STRING "CPU architecture to optimize for. (unused)") + endif() +endmacro() + +macro(OptimizeForArchitectureX86) + set(TARGET_ARCHITECTURE "auto" CACHE STRING "CPU architecture to optimize for. \ +Using an incorrect setting here can result in crashes of the resulting binary because of invalid instructions used. \ +Setting the value to \"auto\" will try to optimize for the architecture where cmake is called. \ +Other supported values are: \"none\", \"generic\", \"core\", \"merom\" (65nm Core2), \ +\"penryn\" (45nm Core2), \"nehalem\", \"westmere\", \"sandy-bridge\", \"ivy-bridge\", \ +\"haswell\", \"broadwell\", \"skylake\", \"skylake-xeon\", \"kaby-lake\", \"cannonlake\", \"silvermont\", \ +\"goldmont\", \"knl\" (Knights Landing), \"atom\", \"k8\", \"k8-sse3\", \"barcelona\", \ +\"istanbul\", \"magny-cours\", \"bulldozer\", \"interlagos\", \"piledriver\", \ +\"AMD 14h\", \"AMD 16h\", \"zen\".") + set(_force) + if(NOT _last_target_arch STREQUAL "${TARGET_ARCHITECTURE}") + message(STATUS "target changed from \"${_last_target_arch}\" to \"${TARGET_ARCHITECTURE}\"") + set(_force FORCE) + endif() + set(_last_target_arch "${TARGET_ARCHITECTURE}" CACHE STRING "" FORCE) + mark_as_advanced(_last_target_arch) + string(TOLOWER "${TARGET_ARCHITECTURE}" TARGET_ARCHITECTURE) + + set(_march_flag_list) + set(_available_vector_units_list) + + if(TARGET_ARCHITECTURE STREQUAL "auto") + AutodetectHostArchitecture() + message(STATUS "Detected CPU: ${TARGET_ARCHITECTURE}") + endif(TARGET_ARCHITECTURE STREQUAL "auto") + + macro(_nehalem) + list(APPEND _march_flag_list "nehalem") + list(APPEND _march_flag_list "corei7") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4.1" "sse4.2") + endmacro() + macro(_westmere) + list(APPEND _march_flag_list "westmere") + _nehalem() + endmacro() + macro(_sandybridge) + list(APPEND _march_flag_list "sandybridge") + list(APPEND _march_flag_list "corei7-avx") + _westmere() + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4.1" "sse4.2" "avx") + endmacro() + macro(_ivybridge) + list(APPEND _march_flag_list "ivybridge") + list(APPEND _march_flag_list "core-avx-i") + _sandybridge() + list(APPEND _available_vector_units_list "rdrnd" "f16c") + endmacro() + macro(_haswell) + list(APPEND _march_flag_list "haswell") + list(APPEND _march_flag_list "core-avx2") + _ivybridge() + list(APPEND _available_vector_units_list "avx2" "fma" "bmi" "bmi2") + endmacro() + macro(_broadwell) + list(APPEND _march_flag_list "broadwell") + _haswell() + endmacro() + macro(_skylake) + list(APPEND _march_flag_list "skylake") + _broadwell() + endmacro() + macro(_skylake_avx512) + list(APPEND _march_flag_list "skylake-avx512") + _skylake() + list(APPEND _available_vector_units_list "avx512f" "avx512cd" "avx512dq" "avx512bw" "avx512vl") + endmacro() + macro(_cannonlake) + list(APPEND _march_flag_list "cannonlake") + _skylake_avx512() + list(APPEND _available_vector_units_list "avx512ifma" "avx512vbmi") + endmacro() + macro(_knightslanding) + list(APPEND _march_flag_list "knl") + _broadwell() + list(APPEND _available_vector_units_list "avx512f" "avx512pf" "avx512er" "avx512cd") + endmacro() + macro(_silvermont) + list(APPEND _march_flag_list "silvermont") + _westmere() + list(APPEND _available_vector_units_list "rdrnd") + endmacro() + macro(_goldmont) + list(APPEND _march_flag_list "goldmont") + _silvermont() + endmacro() + + if(TARGET_ARCHITECTURE STREQUAL "core") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3") + elseif(TARGET_ARCHITECTURE STREQUAL "merom") + list(APPEND _march_flag_list "merom") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3") + elseif(TARGET_ARCHITECTURE STREQUAL "penryn") + list(APPEND _march_flag_list "penryn") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3") + message(STATUS "Sadly the Penryn architecture exists in variants with SSE4.1 and without SSE4.1.") + if(_cpu_flags MATCHES "sse4_1") + message(STATUS "SSE4.1: enabled (auto-detected from this computer's CPU flags)") + list(APPEND _available_vector_units_list "sse4.1") + else() + message(STATUS "SSE4.1: disabled (auto-detected from this computer's CPU flags)") + endif() + elseif(TARGET_ARCHITECTURE STREQUAL "knl") + _knightslanding() + elseif(TARGET_ARCHITECTURE STREQUAL "cannonlake") + _cannonlake() + elseif(TARGET_ARCHITECTURE STREQUAL "kaby-lake") + _skylake() + elseif(TARGET_ARCHITECTURE STREQUAL "skylake-xeon" OR TARGET_ARCHITECTURE STREQUAL "skylake-avx512") + _skylake_avx512() + elseif(TARGET_ARCHITECTURE STREQUAL "skylake") + _skylake() + elseif(TARGET_ARCHITECTURE STREQUAL "broadwell") + _broadwell() + elseif(TARGET_ARCHITECTURE STREQUAL "haswell") + _haswell() + elseif(TARGET_ARCHITECTURE STREQUAL "ivy-bridge") + _ivybridge() + elseif(TARGET_ARCHITECTURE STREQUAL "sandy-bridge") + _sandybridge() + elseif(TARGET_ARCHITECTURE STREQUAL "westmere") + _westmere() + elseif(TARGET_ARCHITECTURE STREQUAL "nehalem") + _nehalem() + elseif(TARGET_ARCHITECTURE STREQUAL "goldmont") + _goldmont() + elseif(TARGET_ARCHITECTURE STREQUAL "silvermont") + _silvermont() + elseif(TARGET_ARCHITECTURE STREQUAL "atom") + list(APPEND _march_flag_list "atom") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3") + elseif(TARGET_ARCHITECTURE STREQUAL "k8") + list(APPEND _march_flag_list "k8") + list(APPEND _available_vector_units_list "sse" "sse2") + elseif(TARGET_ARCHITECTURE STREQUAL "k8-sse3") + list(APPEND _march_flag_list "k8-sse3") + list(APPEND _march_flag_list "k8") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3") + elseif(TARGET_ARCHITECTURE STREQUAL "AMD 16h") + list(APPEND _march_flag_list "btver2") + list(APPEND _march_flag_list "btver1") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4a" "sse4.1" "sse4.2" "avx" "f16c") + elseif(TARGET_ARCHITECTURE STREQUAL "AMD 14h") + list(APPEND _march_flag_list "btver1") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4a") + elseif(TARGET_ARCHITECTURE STREQUAL "zen") + list(APPEND _march_flag_list "znver1") + _skylake() + list(APPEND _available_vector_units_list "sse4a") + elseif(TARGET_ARCHITECTURE STREQUAL "piledriver") + list(APPEND _march_flag_list "bdver2") + list(APPEND _march_flag_list "bdver1") + list(APPEND _march_flag_list "bulldozer") + list(APPEND _march_flag_list "barcelona") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4a" "sse4.1" "sse4.2" "avx" "xop" "fma4" "fma" "f16c") + elseif(TARGET_ARCHITECTURE STREQUAL "interlagos") + list(APPEND _march_flag_list "bdver1") + list(APPEND _march_flag_list "bulldozer") + list(APPEND _march_flag_list "barcelona") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4a" "sse4.1" "sse4.2" "avx" "xop" "fma4") + elseif(TARGET_ARCHITECTURE STREQUAL "bulldozer") + list(APPEND _march_flag_list "bdver1") + list(APPEND _march_flag_list "bulldozer") + list(APPEND _march_flag_list "barcelona") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4a" "sse4.1" "sse4.2" "avx" "xop" "fma4") + elseif(TARGET_ARCHITECTURE STREQUAL "barcelona") + list(APPEND _march_flag_list "barcelona") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "sse4a") + elseif(TARGET_ARCHITECTURE STREQUAL "istanbul") + list(APPEND _march_flag_list "barcelona") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "sse4a") + elseif(TARGET_ARCHITECTURE STREQUAL "magny-cours") + list(APPEND _march_flag_list "barcelona") + list(APPEND _march_flag_list "core2") + list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "sse4a") + elseif(TARGET_ARCHITECTURE STREQUAL "generic") + list(APPEND _march_flag_list "generic") + elseif(TARGET_ARCHITECTURE STREQUAL "none") + # add this clause to remove it from the else clause + else(TARGET_ARCHITECTURE STREQUAL "core") + message(FATAL_ERROR "Unknown target architecture: \"${TARGET_ARCHITECTURE}\". Please set TARGET_ARCHITECTURE to a supported value.") + endif(TARGET_ARCHITECTURE STREQUAL "core") + + if(NOT TARGET_ARCHITECTURE STREQUAL "none") + set(_disable_vector_unit_list) + set(_enable_vector_unit_list) + if(DEFINED Vc_AVX_INTRINSICS_BROKEN AND Vc_AVX_INTRINSICS_BROKEN) + UserWarning("AVX disabled per default because of old/broken toolchain") + set(_avx_broken true) + set(_avx2_broken true) + set(_fma4_broken true) + set(_xop_broken true) + else() + set(_avx_broken false) + if(DEFINED Vc_FMA4_INTRINSICS_BROKEN AND Vc_FMA4_INTRINSICS_BROKEN) + UserWarning("FMA4 disabled per default because of old/broken toolchain") + set(_fma4_broken true) + else() + set(_fma4_broken false) + endif() + if(DEFINED Vc_XOP_INTRINSICS_BROKEN AND Vc_XOP_INTRINSICS_BROKEN) + UserWarning("XOP disabled per default because of old/broken toolchain") + set(_xop_broken true) + else() + set(_xop_broken false) + endif() + if(DEFINED Vc_AVX2_INTRINSICS_BROKEN AND Vc_AVX2_INTRINSICS_BROKEN) + UserWarning("AVX2 disabled per default because of old/broken toolchain") + set(_avx2_broken true) + else() + set(_avx2_broken false) + endif() + endif() + + macro(_enable_or_disable _name _flag _documentation _broken) + if(_broken) + set(_found false) + else() + _my_find(_available_vector_units_list "${_flag}" _found) + endif() + set(USE_${_name} ${_found} CACHE BOOL "${documentation}" ${_force}) + mark_as_advanced(USE_${_name}) + if(USE_${_name}) + list(APPEND _enable_vector_unit_list "${_flag}") + else() + list(APPEND _disable_vector_unit_list "${_flag}") + endif() + endmacro() + _enable_or_disable(SSE2 "sse2" "Use SSE2. If SSE2 instructions are not enabled the SSE implementation will be disabled." false) + _enable_or_disable(SSE3 "sse3" "Use SSE3. If SSE3 instructions are not enabled they will be emulated." false) + _enable_or_disable(SSSE3 "ssse3" "Use SSSE3. If SSSE3 instructions are not enabled they will be emulated." false) + _enable_or_disable(SSE4_1 "sse4.1" "Use SSE4.1. If SSE4.1 instructions are not enabled they will be emulated." false) + _enable_or_disable(SSE4_2 "sse4.2" "Use SSE4.2. If SSE4.2 instructions are not enabled they will be emulated." false) + _enable_or_disable(SSE4a "sse4a" "Use SSE4a. If SSE4a instructions are not enabled they will be emulated." false) + _enable_or_disable(AVX "avx" "Use AVX. This will all floating-point vector sizes relative to SSE." _avx_broken) + _enable_or_disable(FMA "fma" "Use FMA." _avx_broken) + _enable_or_disable(BMI2 "bmi2" "Use BMI2." _avx_broken) + _enable_or_disable(AVX2 "avx2" "Use AVX2. This will double all of the vector sizes relative to SSE." _avx2_broken) + _enable_or_disable(XOP "xop" "Use XOP." _xop_broken) + _enable_or_disable(FMA4 "fma4" "Use FMA4." _fma4_broken) + _enable_or_disable(AVX512F "avx512f" "Use AVX512F. This will double all floating-point vector sizes relative to AVX2." false) + _enable_or_disable(AVX512VL "avx512vl" "Use AVX512VL. This enables 128- and 256-bit vector length instructions with EVEX coding (improved write-masking & more vector registers)." _avx2_broken) + _enable_or_disable(AVX512PF "avx512pf" "Use AVX512PF. This enables prefetch instructions for gathers and scatters." false) + _enable_or_disable(AVX512ER "avx512er" "Use AVX512ER. This enables exponential and reciprocal instructions." false) + _enable_or_disable(AVX512CD "avx512cd" "Use AVX512CD." false) + _enable_or_disable(AVX512DQ "avx512dq" "Use AVX512DQ." false) + _enable_or_disable(AVX512BW "avx512bw" "Use AVX512BW." false) + _enable_or_disable(AVX512IFMA "avx512ifma" "Use AVX512IFMA." false) + _enable_or_disable(AVX512VBMI "avx512vbmi" "Use AVX512VBMI." false) + + if(MSVC) + # MSVC on 32 bit can select /arch:SSE2 (since 2010 also /arch:AVX) + # MSVC on 64 bit cannot select anything (should have changed with MSVC 2010) + _my_find(_enable_vector_unit_list "avx2" _found) + if(_found) + AddCompilerFlag("/arch:AVX2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS CXX_RESULT _found) + endif() + if(NOT _found) + _my_find(_enable_vector_unit_list "avx" _found) + if(_found) + AddCompilerFlag("/arch:AVX" CXX_FLAGS Vc_ARCHITECTURE_FLAGS CXX_RESULT _found) + endif() + endif() + if(NOT _found) + _my_find(_enable_vector_unit_list "sse2" _found) + if(_found) + AddCompilerFlag("/arch:SSE2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS) + endif() + endif() + foreach(_flag ${_enable_vector_unit_list}) + string(TOUPPER "${_flag}" _flag) + string(REPLACE "." "_" _flag "__${_flag}__") + add_definitions("-D${_flag}") + endforeach(_flag) + elseif(CMAKE_CXX_COMPILER MATCHES "/(icpc|icc)$") # ICC (on Linux) + set(OFA_map_knl "-xMIC-AVX512") + set(OFA_map_cannonlake "-xCORE-AVX512") + set(OFA_map_skylake-avx512 "-xCORE-AVX512") + set(OFA_map_skylake "-xCORE-AVX2") + set(OFA_map_broadwell "-xCORE-AVX2") + set(OFA_map_haswell "-xCORE-AVX2") + set(OFA_map_ivybridge "-xCORE-AVX-I") + set(OFA_map_sandybridge "-xAVX") + set(OFA_map_westmere "-xSSE4.2") + set(OFA_map_nehalem "-xSSE4.2") + set(OFA_map_penryn "-xSSSE3") + set(OFA_map_merom "-xSSSE3") + set(OFA_map_core2 "-xSSE3") + set(_ok FALSE) + foreach(arch ${_march_flag_list}) + if(DEFINED OFA_map_${arch}) + AddCompilerFlag(${OFA_map_${arch}} CXX_FLAGS Vc_ARCHITECTURE_FLAGS CXX_RESULT _ok) + if(_ok) + break() + endif() + endif() + endforeach() + if(NOT _ok) + # This is the Intel compiler, so SSE2 is a very reasonable baseline. + message(STATUS "Did not recognize the requested architecture flag, falling back to SSE2") + AddCompilerFlag("-xSSE2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS) + endif() + else() # not MSVC and not ICC => GCC, Clang, Open64 + foreach(_flag ${_march_flag_list}) + AddCompilerFlag("-march=${_flag}" CXX_RESULT _good CXX_FLAGS Vc_ARCHITECTURE_FLAGS) + if(_good) + break() + endif(_good) + endforeach(_flag) + foreach(_flag ${_enable_vector_unit_list}) + AddCompilerFlag("-m${_flag}" CXX_RESULT _result) + if(_result) + set(_header FALSE) + if(_flag STREQUAL "sse3") + set(_header "pmmintrin.h") + elseif(_flag STREQUAL "ssse3") + set(_header "tmmintrin.h") + elseif(_flag STREQUAL "sse4.1") + set(_header "smmintrin.h") + elseif(_flag STREQUAL "sse4.2") + set(_header "smmintrin.h") + elseif(_flag STREQUAL "sse4a") + set(_header "ammintrin.h") + elseif(_flag STREQUAL "avx") + set(_header "immintrin.h") + elseif(_flag STREQUAL "avx2") + set(_header "immintrin.h") + elseif(_flag STREQUAL "fma4") + set(_header "x86intrin.h") + elseif(_flag STREQUAL "xop") + set(_header "x86intrin.h") + endif() + set(_resultVar "HAVE_${_header}") + string(REPLACE "." "_" _resultVar "${_resultVar}") + if(_header) + CHECK_INCLUDE_FILE_CXX("${_header}" ${_resultVar} "-m${_flag}") + if(NOT ${_resultVar}) + set(_useVar "USE_${_flag}") + string(TOUPPER "${_useVar}" _useVar) + string(REPLACE "." "_" _useVar "${_useVar}") + message(STATUS "disabling ${_useVar} because ${_header} is missing") + set(${_useVar} FALSE) + list(APPEND _disable_vector_unit_list "${_flag}") + endif() + endif() + if(NOT _header OR ${_resultVar}) + list(APPEND Vc_ARCHITECTURE_FLAGS "-m${_flag}") + endif() + endif() + endforeach(_flag) + foreach(_flag ${_disable_vector_unit_list}) + AddCompilerFlag("-mno-${_flag}" CXX_FLAGS Vc_ARCHITECTURE_FLAGS) + endforeach(_flag) + endif() + endif() +endmacro() diff --git a/dllsrc/CMakeLists.txt b/dllsrc/CMakeLists.txt new file mode 100644 index 000000000..26b0b9230 --- /dev/null +++ b/dllsrc/CMakeLists.txt @@ -0,0 +1,11 @@ +add_library(j-dll OBJECT EXCLUDE_FROM_ALL) +target_compile_definitions(j-dll PRIVATE $<$:_JDLL>) +target_compile_definitions(j-dll PRIVATE _CRT_SECURE_NO_WARNINGS) +target_sources(j-dll PRIVATE + jdll.c + jdll.h + jdllcom.h + jdllcomx.cpp + jdlltype.h + jexe.h +) diff --git a/dllsrc/jdllcomx.cpp b/dllsrc/jdllcomx.cpp index 0bd45a40d..2a786bd04 100644 --- a/dllsrc/jdllcomx.cpp +++ b/dllsrc/jdllcomx.cpp @@ -270,7 +270,6 @@ STDMETHODIMP CJServer::Invoke(DISPID dispID, REFIID riid { HRESULT hr; ITypeInfo *pTI; - LANGID langID=PRIMARYLANGID(lcid); if (IID_NULL!=riid) return DISP_E_UNKNOWNINTERFACE; hr=GetTypeInfo(0, lcid, &pTI); diff --git a/jsrc/CMakeLists.txt b/jsrc/CMakeLists.txt new file mode 100644 index 000000000..099cd98c1 --- /dev/null +++ b/jsrc/CMakeLists.txt @@ -0,0 +1,278 @@ +if(WIN32) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) +endif() + +add_library(j) +target_compile_definitions(j PRIVATE C_NA=0 C_AVX=1 C_AVX2=1 EMU_AVX=1) +target_link_libraries(j PRIVATE ${STANDARD_MATH_LIBRARY}) +set_source_files_properties(aes-ni.c PROPERTIES COMPILE_FLAGS -maes) +target_sources(j PRIVATE + a.h + aes-arm_table.h + aes-c.h + ar.h + avx2intrin-emu.h + avxintrin-emu.h + avxintrin-neon.h + cip_t.h + cipfloatmm_t.h + cpuinfo.h + cr_t.h + crc32c.h + crc32ctables.h + d.h + dtoa.h + fnmatch.h + gemm.h + j.h + ja.h + jc.h + je.h + jerr.h + jfex.h + js.h + jt.h + jtype.h + jversion.h + linenoise.h + m.h + p.h + result.h + s.h + sse2neon.h + sse2neon2.h + va.h + vasm.h + vcomp.h + vdx.h + ve.h + vg.h + vgmerge.h + vgmergemincomp.h + vgsort.h + vgsortq.h + vq.h + vx.h + vz.h + w.h + x.h + xc.h + a.c + ab.c + aes-c.c + aes-ni.c + aes-sse2.c + af.c + ai.c + am.c + am1.c + amn.c + ao.c + ap.c + ar.c + as.c + au.c + c.c + ca.c + cc.c + cd.c + cf.c + cg.c + ch.c + cip.c + cl.c + cp.c + cpdtsp.c + cpuinfo.c + cr.c + crs.c + ct.c + cu.c + cv.c + cx.c + d.c + dc.c + dss.c + dstop.c + dsusp.c + dtoa.c + f.c + f2.c + fbu.c + gemm.c + i.c + io.c + j.c + jdlllic.c + k.c + m.c + mbx.c + p.c + pv.c + px.c + r.c + rl.c + rt.c + s.c + sc.c + sl.c + sn.c + t.c + u.c + v.c + v0.c + v1.c + v2.c + va1.c + va1ss.c + va2.c + va2s.c + va2ss.c + vamultsp.c + vb.c + vbang.c + vbit.c + vcant.c + vcat.c + vcatsp.c + vchar.c + vcomp.c + vcompsc.c + vd.c + vdx.c + ve.c + vf.c + vfft.c + vfrom.c + vfromsp.c + vg.c + vgauss.c + vgcomp.c + vgranking.c + vgsort.c + vgsp.c + vi.c + viavx.c + viix.c + visp.c + vm.c + vo.c + vp.c + vq.c + vrand.c + vrep.c + vs.c + vsb.c + vt.c + vu.c + vx.c + vz.c + w.c + wc.c + wn.c + ws.c + x.c + x15.c + xa.c + xaes.c + xb.c + xc.c + xcrc.c + xd.c + xf.c + xfmt.c + xh.c + xi.c + xl.c + xo.c + xs.c + xsha.c + xt.c + xu.c + crc32c.c +) + +configure_file(jversion-x.h ${CMAKE_CURRENT_SOURCE_DIR}/jversion.h COPYONLY) + +if("${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC") + get_filename_component(_cl_bin_dir ${CMAKE_C_COMPILER} DIRECTORY) + get_filename_component(OpenMP_libomp_LIB + "${_cl_bin_dir}/../lib/libomp.lib" ABSOLUTE) + file(TO_CMAKE_PATH "${_cl_bin_dir}/libomp.dll" OpenMP_libomp_DLL) +endif() + +if(OpenMP_C_FOUND) + target_link_libraries(j PRIVATE OpenMP::OpenMP_C) + + if(DEFINED OpenMP_libomp_DLL AND + OpenMP_libomp_LIBRARY STREQUAL OpenMP_libomp_LIB) + add_custom_command( + TARGET j POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${OpenMP_libomp_DLL} + $ + ) + endif() +endif() + +target_sources(j PRIVATE + blis.h + blis/gemm_c-ref.c + blis/gemm_int-aarch64.c + blis/gemm_int-avx.c + blis/gemm_int-fma.c + blis/gemm_int-sse2.c + blis/gemm_vec-ref.c +) + +if(NOT BUILD_SHARED_LIBS) + return() +endif() + +add_library(linenoise OBJECT EXCLUDE_FROM_ALL) +target_compile_definitions(linenoise INTERFACE USE_LINENOISE) +target_sources(linenoise PRIVATE + linenoise.h + linenoise.c +) + +add_executable(jconsole) +target_compile_definitions(jconsole PRIVATE READLINE) +if(NOT UNIX OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(aarch64|arm)") + target_link_libraries(jconsole PRIVATE linenoise) +endif() +if("${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC") + target_link_options(jconsole PRIVATE /STACK:0x1000000) +endif() +target_link_libraries(jconsole PRIVATE ${CMAKE_DL_LIBS}) +target_sources(jconsole PRIVATE + jconsole.c + jeload.h + jeload.c + jlib.h + ../makevs/jconsole/jconsole.rc + ../makevs/jconsole/resource1.h + ../makevs/jconsole/jgray.ico +) + +file(TO_NATIVE_PATH "${PROJECT_SOURCE_DIR}/jlibrary/bin" J_BINPATH) +file(TO_NATIVE_PATH "/profile.ijs" J_PROFILE_SCRIPT) +file(GENERATE + OUTPUT "$<${is_multi_config}:$/>profile.ijs" + CONTENT "NB. loaded under debug +BINPATH_z_=: '${J_BINPATH}' +0!:0 -#ifdef MMSC_VER +#ifdef _MSC_VER #pragma warning(disable: 4244) #else #include @@ -283,7 +283,7 @@ JNIEXPORT void JNICALL Java_com_jsoftware_j_JInterface_JSetEnv LOGD("JSetEnv"); const char* key = (*env)->GetStringUTFChars(env, jkey, 0); const char* val = (*env)->GetStringUTFChars(env, jval, 0); -#ifdef MMSC_VER +#ifdef _MSC_VER _putenv_s(key,val); #else setenv(key,val,0); diff --git a/jsrc/openssl/sha/CMakeLists.txt b/jsrc/openssl/sha/CMakeLists.txt new file mode 100644 index 000000000..cfa645245 --- /dev/null +++ b/jsrc/openssl/sha/CMakeLists.txt @@ -0,0 +1,68 @@ +add_library(j-openssl-sha OBJECT) +target_sources(j-openssl-sha PRIVATE + md32_common.h + md4.h + md4_locl.h + md5.h + md5_locl.h + openssl.h + sha.h + sha3.h + sha_locl.h + keccak1600.c + md4_dgst.c + md4_one.c + md5_dgst.c + md5_one.c + openssl-util.c + sha1_one.c + sha256.c + sha3.c + sha512.c +) + +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(aarch64|arm)") + target_sources(j-openssl-sha PRIVATE + $<$:asm/keccak1600-armv8-elf.S> + $<$:asm/sha1-armv8-elf.S> + $<$:asm/sha256-armv8-elf.S> + $<$:asm/sha512-armv8-elf.S> + $<$:asm/keccak1600-armv4-elf.S> + $<$:asm/sha1-armv4-elf.S> + $<$:asm/sha256-armv4-elf.S> + $<$:asm/sha512-armv4-elf.S> + ) +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + target_sources(j PRIVATE + $<$:../openssl-asm/keccak1600-x86_64-nasm.o> + $<$:../openssl-asm/sha1-x86_64-nasm.o> + $<$:../openssl-asm/sha256-x86_64-nasm.o> + $<$:../openssl-asm/sha512-x86_64-nasm.o> + $<$:../openssl-asm/keccak1600-mmx-nasm.o> + $<$:../openssl-asm/sha1-586-nasm.o> + $<$:../openssl-asm/sha256-586-nasm.o> + $<$:../openssl-asm/sha512-586-nasm.o> + ) +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + target_sources(j-openssl-sha PRIVATE + $<$:asm/keccak1600-x86_64-elf.S> + $<$:asm/sha1-x86_64-elf.S> + $<$:asm/sha256-x86_64-elf.S> + $<$:asm/sha512-x86_64-elf.S> + $<$:asm/keccak1600-mmx-elf.S> + $<$:asm/sha1-586-elf.S> + $<$:asm/sha256-586-elf.S> + $<$:asm/sha512-586-elf.S> + ) +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_sources(j-openssl-sha PRIVATE + $<$:asm/keccak1600-x86_64-macho.S> + $<$:asm/sha1-x86_64-macho.S> + $<$:asm/sha256-x86_64-macho.S> + $<$:asm/sha512-x86_64-macho.S> + $<$:asm/keccak1600-mmx-macho.S> + $<$:asm/sha1-586-macho.S> + $<$:asm/sha256-586-macho.S> + $<$:asm/sha512-586-macho.S> + ) +endif() diff --git a/jsrc/xl.c b/jsrc/xl.c index 826ecd27f..6d63d51e4 100644 --- a/jsrc/xl.c +++ b/jsrc/xl.c @@ -17,6 +17,7 @@ static B jtdolock(J jt,B lk,F f,I i,I n){ASSERT(0,EVNONCE);} #if (SYS & SYS_UNIX) || (SY_WIN32 && SYS&SYS_DOS && !SY_WINCE) typedef long long INT64; #include +#include #define LOCK 1 #if (SYS & SYS_UNIX) #include diff --git a/sleef/CMakeLists.txt b/sleef/CMakeLists.txt new file mode 100644 index 000000000..3bdc6dea5 --- /dev/null +++ b/sleef/CMakeLists.txt @@ -0,0 +1,33 @@ +add_library(j-sleef OBJECT) +target_include_directories(j-sleef PRIVATE src/arch src/common) +target_compile_definitions(j-sleef INTERFACE SLEEF=1) +target_compile_definitions(j-sleef PRIVATE SLEEF_STATIC_LIBS ENABLE_AVX2 DORENAME=1) +target_compile_definitions(j-sleef PRIVATE $<$:_CRT_SECURE_NO_WARNINGS>) +target_sources(j-sleef PRIVATE + include/sleef.h + src/arch/avxintrin-emu.h + src/arch/helperadvsimd.h + src/arch/helperavx.h + src/arch/helperavx2.h + src/arch/helpersse2.h + src/arch/helpervecext.h + src/common/arraymap.c + src/common/arraymap.h + src/common/common.c + src/common/common.h + src/common/misc.h + src/libm/dd.h + src/libm/estrin.h + src/libm/funcproto.h + src/libm/importsample.h + src/libm/norename.h + src/libm/rempitab.c + src/libm/rename.h + src/libm/renameadvsimd.h + src/libm/renameadvsimdnofma.h + src/libm/renameavx.h + src/libm/renameavx2.h + src/libm/renamesse2.h + src/libm/renamevecext.h + src/libm/sleefsimddp.c +) diff --git a/sleef/src/common/misc.h b/sleef/src/common/misc.h index b0c07e88c..9014862c0 100644 --- a/sleef/src/common/misc.h +++ b/sleef/src/common/misc.h @@ -257,7 +257,7 @@ typedef union { #else #define CONST #endif -#define INLINE __attribute__((always_inline)) +#define INLINE __attribute__((always_inline)) inline #if defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__) #ifndef SLEEF_STATIC_LIBS diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 000000000..34b13ba05 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,433 @@ +if(BUILD_TESTING) + add_library(tsdll SHARED) + target_link_libraries(tsdll PRIVATE ${STANDARD_MATH_LIBRARY}) + target_sources(tsdll PRIVATE + ../jsrc/tsdll.c + ../makevs/tsdll/tsdll.def + ) +endif() + +set(test_cases + g0 + g000 + g000a + g000i + g000p + g000s + g001 + g010 + g010a + g010i + g010p + g010s + g011 + g011a + g011i + g011p + g011s + g012 + g012a + g012i + g012p + g012s + g020 + g020a + g020i + g020p + g020s + g021 + g021a + g021i + g021p + g021s + g022 + g022a + g022i + g022p + g022s + g030 + g030a + g031 + g032 + g0a + g0x + g100 + g100a + g100i + g100p + g100s + g101 + g101a + g101i + g101p + g101s + g102 + g102a + g102i + g102p + g102s + g110 + g110a + g110i + g110p + g110s + g111 + g111a + g111i + g111p + g111s + g112 + g112a + g112i + g112p + g112s + g120 + g120a + g120i + g120p + g120s + g121 + g122 + g122a + g128x + g128x3 + g128x5 + g128x6 + g128x7 + g130 + g130a + g130i + g130p + g131 + g132 + g13x + g15x + g18x + g1x + g1x0 + g1x1 + g1x11 + g1x12 + g1x2 + g1x20 + g1x3 + g1x30 + g1x4 + g1x43 + g1x5 + g1x55 + g1x7 + g200 + g200a + g200i + g200m + g200p + g201 + g202 + g202b + g210 + g210a + g211 + g212 + g220 + g220t + g221 + g222 + g222a + g222i + g222p + g222s + g230 + g230a + g230i + g230p + g230s + g231 + g232 + g2x + g300 + g300b + g300t + g301 + g310 + g310a + g310names + g310r + g310t + g311 + g312 + g320 + g320ip + g320ipt + g321 + g321t + g322 + g330 + g330f + g330t + g331 + g331bx + g331col + g331ins + g331ps + g331sp + g332 + g332s + g3x + g3x4 + g3x5 + g3x6 + g400 + g400e + g401 + g402 + g410 + g410a + g410i + g410p + g410s + g411 + g412 + # g420 + g420ce + g420fg + g420r2 + g420stch + g420t + g421 + g421c + g421d + g421e + g421i + g421p + g421t + g422 + g422os + g422rk + g422sort + g422sort1 + g422tao + g430 + g430a2 + g430avg + g430b + g430d + g430fin + g430inv + g431 + g431a + g432 + g4x + g4x5 + g500 + g502 + g510 + g520 + g520b + g520p + g521 + g522 + g530 + g530t + g531 + g532 + g5x + g5x0 + g5x1 + g5x2 + g5x30 + g5x4 + g5x5 + g5x6 + g5x7 + g600 + g600ip + g601 + g602 + g610 + g612 + g620 + g620a + g621 + g622 + g630 + g631 + g631c + g632 + g640 + g640k + g640r + g641 + g6x + g6x0 + g6x14 + g7x + g7x5 + g7x6 + g8x + g9x + g9x40 + ga + gassert + gb + gbpar + gc + gchar + gcompsc + gct + gctrl + gd + gddot + gdll + gdll_df + ge + gebar + gesc + gf + gfor + gft + ggoto + gh + gi + gi0 + gibs + gibst + gicap + gicap2 + gico + giconv + gif + gimaxmin + gintdiv + gintg + gintovfl + giph + gipht + giscode + git + gix + gj + glco + gldot + glocale + gmean + gmemo + gmmf + gmmf1s + gmmf1u + gmmf1w + gmnom + gn + gnan + gnum + gnvv + go + goi + goox + gop + gos + gparse + gpco + gpco2 + gpcoinv + gpdd + gpi + gpick + gpoly + gq + gq101 + gq132 + gq201 + gqco + gqnonrat + gr + gr1 + grefcount + gs + gsco + gsco1 + gsco1u + gsco1w + gsco2 + gsco2u + gsco2w + gscou + gsdot + gselect + gsp + gsp0 + gsp000 + gsp1 + gsp100 + gsp101 + gsp102 + gsp110 + gsp111 + gsp112 + gsp120 + gsp122 + gsp130 + gsp2 + gsp221 + gsp222 + gsp231 + gsp320 + gsp321 + gsp322 + gsp331 + gsp400 + gsp410 + gsp412 + gsp420 + gsp421 + gsp422 + gsp431 + gsp432 + gsp520 + gsp520sd + gsp520ss + gsp521 + gsp530i + gsp530l + gsp530n + gsp531 + gsp5x5 + gsp6 + gsp600 + gsp600a + gspi + gspj + gspo + gspr + gspx + gss + gstack + gt + gthrow + gtrain + gtry + gu + gu0 + gunderai + gwhile + gx + gx132 + gxco + gxco1 + gxco2 + gxinf +) + +foreach(test_name IN LISTS test_cases) + file(GENERATE + OUTPUT "$<${is_multi_config}:$/>${test_name}.ijs" + CONTENT "0!:0 <'${CMAKE_CURRENT_SOURCE_DIR}/tsu.ijs' +LIBTSDLL=:'$ ' +exit -.&(0!:3) + ) + add_test( + NAME ${test_name} + COMMAND jconsole "$<${is_multi_config}:$/>${test_name}.ijs" + ) +endforeach()