From 0a90913abf9390b9e08ab6d3b40ac11634553f38 Mon Sep 17 00:00:00 2001 From: Mark Gillard Date: Tue, 15 Nov 2022 21:38:28 +0200 Subject: [PATCH] added `TOML_ENABLE_FLOAT16` config to fix #178 --- CHANGELOG.md | 1 + README.md | 1 + include/toml++/impl/forward_declarations.h | 8 +-- include/toml++/impl/preprocessor.h | 56 ++++++++++++++--- include/toml++/toml.h | 10 +++- meson.build | 28 ++------- meson_options.txt | 1 + src/meson.build | 9 +++ tests/impl_toml.cpp | 8 +-- tests/meson.build | 9 +-- tests/tests.h | 4 +- toml.hpp | 70 +++++++++++++++++----- tools/generate_single_header.py | 1 + 13 files changed, 141 insertions(+), 65 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcd3f4b..5a93001 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ template: - fixed some `_Float16` detection issues - fixed `toml::parse_file()` on windows for non-ASCII paths - added `toml::format_flags::terse_key_value_pairs` +- added `TOML_ENABLE_FLOAT16` config to fix #178 (@Scrumplex)

diff --git a/README.md b/README.md index 56f69e5..8d7afac 100644 --- a/README.md +++ b/README.md @@ -209,6 +209,7 @@ won't need to mess with these at all, but if you do, set them before including t | `TOML_CALLCONV` | define | Calling convention to apply to exported free/static functions. | undefined | | `TOML_CONFIG_HEADER` | string literal | Includes the given header file before the rest of the library. | undefined | | `TOML_ENABLE_FORMATTERS` | boolean | Enables the formatters. Set to `0` if you don't need them to improve compile times and binary size. | `1` | +| `TOML_ENABLE_FLOAT16` | boolean | Enables support for the built-in `_Float16` type. | per compiler settings | | `TOML_ENABLE_PARSER` | boolean | Enables the parser. Set to `0` if you don't need it to improve compile times and binary size. | `1` | | `TOML_ENABLE_UNRELEASED_FEATURES` | boolean | Enables support for [unreleased TOML language features]. | `0` | | `TOML_ENABLE_WINDOWS_COMPAT` | boolean | Enables support for transparent conversion between wide and narrow strings. | `1` on Windows | diff --git a/include/toml++/impl/forward_declarations.h b/include/toml++/impl/forward_declarations.h index 6d110fd..49f6ac5 100644 --- a/include/toml++/impl/forward_declarations.h +++ b/include/toml++/impl/forward_declarations.h @@ -628,9 +628,9 @@ TOML_IMPL_NAMESPACE_START template struct float_traits : float_traits_base::digits, std::numeric_limits::digits10> {}; -#ifdef TOML_FLOAT16 +#if TOML_ENABLE_FLOAT16 template <> - struct float_traits : float_traits_base + struct float_traits<_Float16> : float_traits_base<_Float16, __FLT16_MANT_DIG__, __FLT16_DIG__> {}; #endif #ifdef TOML_FLOAT128 @@ -649,9 +649,9 @@ TOML_IMPL_NAMESPACE_START template <> struct value_traits : float_traits {}; -#ifdef TOML_FLOAT16 +#if TOML_ENABLE_FLOAT16 template <> - struct value_traits : float_traits + struct value_traits<_Float16> : float_traits<_Float16> {}; #endif #ifdef TOML_FLOAT128 diff --git a/include/toml++/impl/preprocessor.h b/include/toml++/impl/preprocessor.h index 9cf8e46..7305218 100644 --- a/include/toml++/impl/preprocessor.h +++ b/include/toml++/impl/preprocessor.h @@ -1055,7 +1055,34 @@ TOML_ENABLE_WARNINGS; //# FLOAT16 //#===================================================================================================================== -#if TOML_CLANG +#ifndef TOML_ENABLE_FLOAT16 + +#ifdef __FLT16_MANT_DIG__ +#define TOML_FLOAT16_MANT_DIG __FLT16_MANT_DIG__ +#define TOML_FLOAT16_DIG __FLT16_DIG__ +#define TOML_FLOAT16_MIN_EXP __FLT16_MIN_EXP__ +#define TOML_FLOAT16_MIN_10_EXP __FLT16_MIN_10_EXP__ +#define TOML_FLOAT16_MAX_EXP __FLT16_MAX_EXP__ +#define TOML_FLOAT16_MAX_10_EXP __FLT16_MAX_10_EXP__ +#else +#define TOML_FLOAT16_MANT_DIG 0 +#define TOML_FLOAT16_DIG 0 +#define TOML_FLOAT16_MIN_EXP 0 +#define TOML_FLOAT16_MIN_10_EXP 0 +#define TOML_FLOAT16_MAX_EXP 0 +#define TOML_FLOAT16_MAX_10_EXP 0 +#endif + +#if (TOML_FLOAT16_MANT_DIG && TOML_FLOAT16_DIG && TOML_FLOAT16_MIN_EXP && TOML_FLOAT16_MIN_10_EXP \ + && TOML_FLOAT16_MAX_EXP && TOML_FLOAT16_MAX_10_EXP) +#define TOML_FLOAT16_LIMITS_SET 1 +#else +#define TOML_FLOAT16_LIMITS_SET 0 +#endif + +#if TOML_FLOAT16_LIMITS_SET + +#if TOML_CLANG // >= 15 //# {{ // Excerpt from https://clang.llvm.org/docs/LanguageExtensions.html: // @@ -1069,9 +1096,10 @@ TOML_ENABLE_WARNINGS; // X86 as long as SSE2 is available // //# }} -#if (TOML_ARCH_ARM || TOML_ARCH_X86 || TOML_ARCH_AMD64) && defined(__FLT16_MANT_DIG__) -#define TOML_FLOAT16 _Float16 +#if (TOML_ARCH_ARM || TOML_ARCH_AMD64 || TOML_ARCH_X86) +#define TOML_ENABLE_FLOAT16 1 #endif + #elif TOML_GCC //# {{ // Excerpt from https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html: @@ -1082,13 +1110,25 @@ TOML_ENABLE_WARNINGS; // // *** except: the bit about x86 seems incorrect?? *** //# }} -/* +#if (TOML_ARCH_ARM || TOML_ARCH_AMD64 /* || TOML_ARCH_X86*/) +#define TOML_ENABLE_FLOAT16 1 +#endif - */ -#if (TOML_ARCH_ARM /*|| TOML_ARCH_X86 || TOML_ARCH_AMD64*/) && defined(__FLT16_MANT_DIG__) -#define TOML_FLOAT16 _Float16 -#endif +#endif // clang/gcc + +#endif // TOML_FLOAT16_LIMITS_SET + +#endif // !defined(TOML_ENABLE_FLOAT16) + +#ifndef TOML_ENABLE_FLOAT16 +#define TOML_ENABLE_FLOAT16 0 #endif +//# {{ +/// \def TOML_ENABLE_FLOAT16 +/// \brief Enable support for the built-in `_Float16` type. +/// \detail Default behaviour is to try to determine support based on compiler, architecture and built-in defines, but +/// you can override it to force-enable/disable support. +//# }} //#===================================================================================================================== //# FLOAT128 diff --git a/include/toml++/toml.h b/include/toml++/toml.h index f7db954..8ac1a37 100644 --- a/include/toml++/toml.h +++ b/include/toml++/toml.h @@ -90,8 +90,8 @@ TOML_POP_WARNINGS; #undef TOML_ANON_NAMESPACE #undef TOML_ANON_NAMESPACE_END #undef TOML_ANON_NAMESPACE_START -#undef TOML_ARCH_ARM #undef TOML_ARCH_AMD64 +#undef TOML_ARCH_ARM #undef TOML_ARCH_ARM32 #undef TOML_ARCH_ARM64 #undef TOML_ARCH_ITANIUM @@ -131,7 +131,13 @@ TOML_POP_WARNINGS; #undef TOML_FLAGS_ENUM #undef TOML_FLOAT_CHARCONV #undef TOML_FLOAT128 -#undef TOML_FLOAT16 +#undef TOML_FLOAT16_DIG +#undef TOML_FLOAT16_LIMITS_SET +#undef TOML_FLOAT16_MANT_DIG +#undef TOML_FLOAT16_MAX_10_EXP +#undef TOML_FLOAT16_MAX_EXP +#undef TOML_FLOAT16_MIN_10_EXP +#undef TOML_FLOAT16_MIN_EXP #undef TOML_GCC #undef TOML_HAS_ATTR #undef TOML_HAS_BUILTIN diff --git a/meson.build b/meson.build index c815225..3dd9735 100644 --- a/meson.build +++ b/meson.build @@ -319,27 +319,11 @@ compiler_supports_consteval_properly = compiler_supports_consteval and not compi ) ####################################################################################################################### -# __fp16 and _Float16 checks +# _Float16 checks ####################################################################################################################### -compiler_supports_float16_args = [] -if is_gcc - compiler_supports_float16_args += '-mfp16-format=ieee' -endif -compiler_supports_fp16 = compiler.links(''' - int main() - { - static_assert(sizeof(__fp16) == 2); - __fp16 f = static_cast<__fp16>(1); - const auto f2 = static_cast(f); - const auto f3 = static_cast<__fp16>(0.2L); - return 0; - } - ''', - name: 'supports __fp16', - args: compiler_supports_float16_args -) -compiler_supports_float16 = compiler.links(''' +compiler_supports_float16_args = compiler.get_supported_arguments('-mfp16-format=ieee') +compiler_supports_float16 = get_option('float16') and compiler.links(''' int main() { static_assert(sizeof(_Float16) == 2); @@ -352,7 +336,7 @@ compiler_supports_float16 = compiler.links(''' name: 'supports _Float16', args: compiler_supports_float16_args ) -if compiler_supports_fp16 or compiler_supports_float16 +if compiler_supports_float16 devel_args += compiler_supports_float16_args endif @@ -411,8 +395,8 @@ compiler_supports_float128 = compiler.links(''' name: 'supports __float128' ) -if compiler_supports_float128 and is_gcc and not is_subproject - add_global_arguments('-fext-numeric-literals', language: 'cpp') +if compiler_supports_float16 or compiler_supports_float128 or compiler_supports_int128 + devel_args += compiler.get_supported_arguments('-fext-numeric-literals') endif ####################################################################################################################### diff --git a/meson_options.txt b/meson_options.txt index 885040c..13c9a45 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -11,3 +11,4 @@ option('build_tt_encoder', type: 'boolean', value: false, description: 'Enable option('build_tt_decoder', type: 'boolean', value: false, description: 'Enable to build the toml-test decoder.') option('compile_library', type: 'boolean', value: false, description: 'Compile as a library') option('use_vendored_libs', type: 'boolean', value: true, description: 'Use the libs from the vendor dir when building tests.') +option('float16', type: 'boolean', value: true, description: 'Use _Float16 automatically where available.') diff --git a/src/meson.build b/src/meson.build index a49cb1f..b64ba54 100644 --- a/src/meson.build +++ b/src/meson.build @@ -6,6 +6,15 @@ lib_args = ['-DTOML_HEADER_ONLY=0'] if get_option('default_library') != 'static' lib_args += '-DTOML_SHARED_LIB=1' endif +if compiler_supports_float16 + lib_args += compiler_supports_float16_args + lib_args += '-DTOML_ENABLE_FLOAT16=1' +else + lib_args += '-DTOML_ENABLE_FLOAT16=0' +endif +if compiler_supports_float16 or compiler_supports_float128 or compiler_supports_int128 + lib_args += compiler.get_supported_arguments('-fext-numeric-literals') +endif lib = library( meson.project_name(), diff --git a/tests/impl_toml.cpp b/tests/impl_toml.cpp index 37c02a6..95a8d92 100644 --- a/tests/impl_toml.cpp +++ b/tests/impl_toml.cpp @@ -64,8 +64,8 @@ namespace toml CHECK_CAN_REPRESENT_NATIVE(TOML_INT128, true); CHECK_CAN_REPRESENT_NATIVE(TOML_UINT128, false); #endif -#ifdef TOML_FLOAT16 - CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT16, false); +#if TOML_ENABLE_FLOAT16 + CHECK_CAN_REPRESENT_NATIVE(_Float16, false); #endif #ifdef TOML_FLOAT128 CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT128, true); @@ -289,8 +289,8 @@ namespace toml CHECK_INSERTED_AS(uint32_t, value); CHECK_INSERTED_AS(float, value); CHECK_INSERTED_AS(double, value); -#ifdef TOML_FLOAT16 - CHECK_INSERTED_AS(TOML_FLOAT16, value); +#if TOML_ENABLE_FLOAT16 + CHECK_INSERTED_AS(_Float16, value); #endif #define CHECK_NODE_REF_TYPE(T) \ diff --git a/tests/meson.build b/tests/meson.build index 6c3b811..97f3cd5 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -39,13 +39,7 @@ endif # fast math check ####################################################################################################################### -compiler_supports_fast_math_args = [] -if is_gcc or is_clang - compiler_supports_fast_math_args += '-ffast-math' - compiler_supports_fast_math_args += '-ffp-contract=fast' -elif is_msvc or is_icc_cl - compiler_supports_fast_math_args += '/fp:fast' -endif +compiler_supports_fast_math_args = compiler.get_supported_arguments('-ffast-math', '-ffp-contract=fast', '/fp:fast') compiler_supports_fast_math = compiler.links(''' #include #include @@ -58,7 +52,6 @@ compiler_supports_fast_math = compiler.links(''' name: 'supports fast-math', args: compiler_supports_fast_math_args ) - ####################################################################################################################### # do the thing! ####################################################################################################################### diff --git a/tests/tests.h b/tests/tests.h index 5756a27..3d93069 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -11,8 +11,8 @@ #else #include "../include/toml++/toml.h" #endif -#if defined(TOML_FLOAT16) ^ SHOULD_HAVE_FLOAT16 -#error TOML_FLOAT16 was not deduced correctly +#if TOML_ENABLE_FLOAT16 ^ SHOULD_HAVE_FLOAT16 +#error TOML_ENABLE_FLOAT16 was not deduced correctly #endif #if defined(TOML_FLOAT128) ^ SHOULD_HAVE_FLOAT128 #error TOML_FLOAT128 was not deduced correctly diff --git a/toml.hpp b/toml.hpp index 7171b54..5e4c7f8 100644 --- a/toml.hpp +++ b/toml.hpp @@ -930,17 +930,51 @@ TOML_ENABLE_WARNINGS; TOML_REQUIRES(condition) #define TOML_HIDDEN_CONSTRAINT(condition, ...) TOML_CONSTRAINED_TEMPLATE(condition, __VA_ARGS__) -#if TOML_CLANG -#if (TOML_ARCH_ARM || TOML_ARCH_X86 || TOML_ARCH_AMD64) && defined(__FLT16_MANT_DIG__) -#define TOML_FLOAT16 _Float16 -#endif -#elif TOML_GCC -/* +#ifndef TOML_ENABLE_FLOAT16 - */ -#if (TOML_ARCH_ARM /*|| TOML_ARCH_X86 || TOML_ARCH_AMD64*/) && defined(__FLT16_MANT_DIG__) -#define TOML_FLOAT16 _Float16 +#ifdef __FLT16_MANT_DIG__ +#define TOML_FLOAT16_MANT_DIG __FLT16_MANT_DIG__ +#define TOML_FLOAT16_DIG __FLT16_DIG__ +#define TOML_FLOAT16_MIN_EXP __FLT16_MIN_EXP__ +#define TOML_FLOAT16_MIN_10_EXP __FLT16_MIN_10_EXP__ +#define TOML_FLOAT16_MAX_EXP __FLT16_MAX_EXP__ +#define TOML_FLOAT16_MAX_10_EXP __FLT16_MAX_10_EXP__ +#else +#define TOML_FLOAT16_MANT_DIG 0 +#define TOML_FLOAT16_DIG 0 +#define TOML_FLOAT16_MIN_EXP 0 +#define TOML_FLOAT16_MIN_10_EXP 0 +#define TOML_FLOAT16_MAX_EXP 0 +#define TOML_FLOAT16_MAX_10_EXP 0 #endif + +#if (TOML_FLOAT16_MANT_DIG && TOML_FLOAT16_DIG && TOML_FLOAT16_MIN_EXP && TOML_FLOAT16_MIN_10_EXP \ + && TOML_FLOAT16_MAX_EXP && TOML_FLOAT16_MAX_10_EXP) +#define TOML_FLOAT16_LIMITS_SET 1 +#else +#define TOML_FLOAT16_LIMITS_SET 0 +#endif + +#if TOML_FLOAT16_LIMITS_SET + +#if TOML_CLANG // >= 15 +#if (TOML_ARCH_ARM || TOML_ARCH_AMD64 || TOML_ARCH_X86) +#define TOML_ENABLE_FLOAT16 1 +#endif + +#elif TOML_GCC +#if (TOML_ARCH_ARM || TOML_ARCH_AMD64 /* || TOML_ARCH_X86*/) +#define TOML_ENABLE_FLOAT16 1 +#endif + +#endif // clang/gcc + +#endif // TOML_FLOAT16_LIMITS_SET + +#endif // !defined(TOML_ENABLE_FLOAT16) + +#ifndef TOML_ENABLE_FLOAT16 +#define TOML_ENABLE_FLOAT16 0 #endif #if defined(__SIZEOF_FLOAT128__) && defined(__FLT128_MANT_DIG__) && defined(__LDBL_MANT_DIG__) \ @@ -1701,9 +1735,9 @@ TOML_IMPL_NAMESPACE_START template struct float_traits : float_traits_base::digits, std::numeric_limits::digits10> {}; -#ifdef TOML_FLOAT16 +#if TOML_ENABLE_FLOAT16 template <> - struct float_traits : float_traits_base + struct float_traits<_Float16> : float_traits_base<_Float16, __FLT16_MANT_DIG__, __FLT16_DIG__> {}; #endif #ifdef TOML_FLOAT128 @@ -1722,9 +1756,9 @@ TOML_IMPL_NAMESPACE_START template <> struct value_traits : float_traits {}; -#ifdef TOML_FLOAT16 +#if TOML_ENABLE_FLOAT16 template <> - struct value_traits : float_traits + struct value_traits<_Float16> : float_traits<_Float16> {}; #endif #ifdef TOML_FLOAT128 @@ -17091,8 +17125,8 @@ TOML_POP_WARNINGS; #undef TOML_ANON_NAMESPACE #undef TOML_ANON_NAMESPACE_END #undef TOML_ANON_NAMESPACE_START -#undef TOML_ARCH_ARM #undef TOML_ARCH_AMD64 +#undef TOML_ARCH_ARM #undef TOML_ARCH_ARM32 #undef TOML_ARCH_ARM64 #undef TOML_ARCH_ITANIUM @@ -17132,7 +17166,13 @@ TOML_POP_WARNINGS; #undef TOML_FLAGS_ENUM #undef TOML_FLOAT_CHARCONV #undef TOML_FLOAT128 -#undef TOML_FLOAT16 +#undef TOML_FLOAT16_DIG +#undef TOML_FLOAT16_LIMITS_SET +#undef TOML_FLOAT16_MANT_DIG +#undef TOML_FLOAT16_MAX_10_EXP +#undef TOML_FLOAT16_MAX_EXP +#undef TOML_FLOAT16_MIN_10_EXP +#undef TOML_FLOAT16_MIN_EXP #undef TOML_GCC #undef TOML_HAS_ATTR #undef TOML_HAS_BUILTIN diff --git a/tools/generate_single_header.py b/tools/generate_single_header.py index 6df41bf..18f0a19 100755 --- a/tools/generate_single_header.py +++ b/tools/generate_single_header.py @@ -215,6 +215,7 @@ def main(): r'TOML_ENABLE_SIMD', r'TOML_ENABLE_UNRELEASED_FEATURES', r'TOML_ENABLE_WINDOWS_COMPAT', + r'TOML_ENABLE_FLOAT16', r'TOML_EXCEPTIONS', r'TOML_EXPORTED_CLASS', r'TOML_EXPORTED_FREE_FUNCTION',