diff --git a/libc/docs/headers/complex.rst b/libc/docs/headers/complex.rst index 272cf00c883bc..7195f2695457e 100644 --- a/libc/docs/headers/complex.rst +++ b/libc/docs/headers/complex.rst @@ -10,7 +10,7 @@ Macros +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | | (float) | (double) | (long double) | (float16) | (float128) | C23 Definition Section | C23 Error Handling Section | +===========+==================+=================+========================+======================+========================+========================+============================+ -| CMPLX | | | | | | 7.3.9.3 | N/A | +| CMPLX | |check| | |check| | |check| | |check| | |check| | 7.3.9.3 | N/A | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ Functions diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt index 7aa549ddc75d9..f71540313f0b3 100644 --- a/libc/include/llvm-libc-macros/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/CMakeLists.txt @@ -61,10 +61,25 @@ add_macro_header( fcntl-macros.h ) +add_macro_header( + cfloat128_macros + HDR + cfloat128-macros.h +) + +add_macro_header( + cfloat16_macros + HDR + cfloat16-macros.h +) + add_macro_header( complex_macros HDR complex-macros.h + DEPENDS + .cfloat128_macros + .cfloat16_macros ) add_macro_header( diff --git a/libc/include/llvm-libc-macros/cfloat128-macros.h b/libc/include/llvm-libc-macros/cfloat128-macros.h new file mode 100644 index 0000000000000..5f28cfa21aaee --- /dev/null +++ b/libc/include/llvm-libc-macros/cfloat128-macros.h @@ -0,0 +1,41 @@ +//===-- Detection of _Complex _Float128 compiler builtin type -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_MACROS_CFLOAT128_MACROS_H +#define LLVM_LIBC_MACROS_CFLOAT128_MACROS_H + +#include "float-macros.h" // LDBL_MANT_DIG + +// Currently, the complex variant of C23 `_Float128` type is only defined as a +// built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For +// clang, the complex variant of `__float128` is defined instead, and only on +// x86-64 targets for clang 11 or later. +// +// TODO: Update the complex variant of C23 `_Float128` type detection again when +// clang supports it. +#ifdef __clang__ +#if (__clang_major__ >= 11) && \ + (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) +// Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__ +// macro to notify the availability of __float128 type: +// https://reviews.llvm.org/D15120 +#define LIBC_TYPES_HAS_CFLOAT128 +#endif +#elif defined(__GNUC__) +#if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \ + (__GNUC__ >= 13 || (!defined(__cplusplus))) +#define LIBC_TYPES_HAS_CFLOAT128 +#endif +#endif + +#if !defined(LIBC_TYPES_HAS_CFLOAT128) && (LDBL_MANT_DIG == 113) +#define LIBC_TYPES_HAS_CFLOAT128 +#define LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE +#endif + +#endif // LLVM_LIBC_MACROS_CFLOAT128_MACROS_H diff --git a/libc/include/llvm-libc-macros/cfloat16-macros.h b/libc/include/llvm-libc-macros/cfloat16-macros.h new file mode 100644 index 0000000000000..1f10adf3e3f2d --- /dev/null +++ b/libc/include/llvm-libc-macros/cfloat16-macros.h @@ -0,0 +1,20 @@ +//===-- Detection of _Complex _Float16 compiler builtin type --------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_MACROS_CFLOAT16_MACROS_H +#define LLVM_LIBC_MACROS_CFLOAT16_MACROS_H + +#if defined(__FLT16_MANT_DIG__) && \ + (!defined(__GNUC__) || __GNUC__ >= 13 || \ + (defined(__clang__) && __clang_major__ >= 14)) && \ + !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \ + !defined(_WIN32) +#define LIBC_TYPES_HAS_CFLOAT16 +#endif + +#endif // LLVM_LIBC_MACROS_CFLOAT16_MACROS_H diff --git a/libc/include/llvm-libc-macros/complex-macros.h b/libc/include/llvm-libc-macros/complex-macros.h index 427c68d289e0b..d98c6fdb306c8 100644 --- a/libc/include/llvm-libc-macros/complex-macros.h +++ b/libc/include/llvm-libc-macros/complex-macros.h @@ -9,6 +9,9 @@ #ifndef __LLVM_LIBC_MACROS_COMPLEX_MACROS_H #define __LLVM_LIBC_MACROS_COMPLEX_MACROS_H +#include "cfloat128-macros.h" +#include "cfloat16-macros.h" + #ifndef __STDC_NO_COMPLEX__ #define __STDC_VERSION_COMPLEX_H__ 202311L @@ -19,6 +22,23 @@ // TODO: Add imaginary macros once GCC or Clang support _Imaginary builtin-type. +#define CMPLX(x, y) __builtin_complex((double)(x), (double)(y)) +#define CMPLXF(x, y) __builtin_complex((float)(x), (float)(y)) +#define CMPLXL(x, y) __builtin_complex((long double)(x), (long double)(y)) + +#ifdef LIBC_TYPES_HAS_CFLOAT16 +#if !defined(__clang__) || (__clang_major__ >= 22 && __clang_minor__ > 0) +#define CMPLXF16(x, y) __builtin_complex((_Float16)(x), (_Float16)(y)) +#else +#define CMPLXF16(x, y) \ + ((complex _Float16)(__builtin_complex((float)(x), (float)(y)))) #endif +#endif // LIBC_TYPES_HAS_CFLOAT16 + +#ifdef LIBC_TYPES_HAS_CFLOAT128 +#define CMPLXF128(x, y) __builtin_complex((float128)(x), (float128)(y)) +#endif // LIBC_TYPES_HAS_CFLOAT128 + +#endif // __STDC_NO_COMPLEX__ #endif // __LLVM_LIBC_MACROS_COMPLEX_MACROS_H diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt index fe9e4e397666e..70da983be9090 100644 --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -150,9 +150,15 @@ add_header( HDR cfloat128.h DEPENDS - libc.include.llvm-libc-macros.float_macros + libc.include.llvm-libc-macros.cfloat128_macros +) +add_header( + cfloat16 + HDR + cfloat16.h + DEPENDS + libc.include.llvm-libc-macros.cfloat16_macros ) -add_header(cfloat16 HDR cfloat16.h) add_header(fsblkcnt_t HDR fsblkcnt_t.h) add_header(fsfilcnt_t HDR fsfilcnt_t.h) add_header( diff --git a/libc/include/llvm-libc-types/cfloat128.h b/libc/include/llvm-libc-types/cfloat128.h index 83fad87910137..25b4cc7345a30 100644 --- a/libc/include/llvm-libc-types/cfloat128.h +++ b/libc/include/llvm-libc-types/cfloat128.h @@ -9,36 +9,14 @@ #ifndef LLVM_LIBC_TYPES_CFLOAT128_H #define LLVM_LIBC_TYPES_CFLOAT128_H -#include "../llvm-libc-macros/float-macros.h" // LDBL_MANT_DIG +#include "../llvm-libc-macros/cfloat128-macros.h" -// Currently, the complex variant of C23 `_Float128` type is only defined as a -// built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For -// clang, the complex variant of `__float128` is defined instead, and only on -// x86-64 targets for clang 11 or later. -// -// TODO: Update the complex variant of C23 `_Float128` type detection again when -// clang supports it. -#ifdef __clang__ -#if (__clang_major__ >= 11) && \ - (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) -// Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__ -// macro to notify the availability of __float128 type: -// https://reviews.llvm.org/D15120 -#define LIBC_TYPES_HAS_CFLOAT128 +#ifdef LIBC_TYPES_HAS_CFLOAT128 +#ifndef LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE typedef _Complex __float128 cfloat128; -#endif -#elif defined(__GNUC__) -#if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \ - (__GNUC__ >= 13 || (!defined(__cplusplus))) -#define LIBC_TYPES_HAS_CFLOAT128 -typedef _Complex _Float128 cfloat128; -#endif -#endif - -#if !defined(LIBC_TYPES_HAS_CFLOAT128) && (LDBL_MANT_DIG == 113) -#define LIBC_TYPES_HAS_CFLOAT128 -#define LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE +#else typedef _Complex long double cfloat128; -#endif +#endif // LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE +#endif // LIBC_TYPES_HAS_CFLOAT128 #endif // LLVM_LIBC_TYPES_CFLOAT128_H diff --git a/libc/include/llvm-libc-types/cfloat16.h b/libc/include/llvm-libc-types/cfloat16.h index 2d4cef7562720..644a6469f0592 100644 --- a/libc/include/llvm-libc-types/cfloat16.h +++ b/libc/include/llvm-libc-types/cfloat16.h @@ -9,13 +9,10 @@ #ifndef LLVM_LIBC_TYPES_CFLOAT16_H #define LLVM_LIBC_TYPES_CFLOAT16_H -#if defined(__FLT16_MANT_DIG__) && \ - (!defined(__GNUC__) || __GNUC__ >= 13 || \ - (defined(__clang__) && __clang_major__ >= 14)) && \ - !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \ - !defined(_WIN32) -#define LIBC_TYPES_HAS_CFLOAT16 +#include "../llvm-libc-macros/cfloat16-macros.h" + +#ifdef LIBC_TYPES_HAS_CFLOAT16 typedef _Complex _Float16 cfloat16; -#endif +#endif // LIBC_TYPES_HAS_CFLOAT16 #endif // LLVM_LIBC_TYPES_CFLOAT16_H diff --git a/libc/test/include/complex_test.cpp b/libc/test/include/complex_test.cpp index da833fb527381..6f900aa4fb674 100644 --- a/libc/test/include/complex_test.cpp +++ b/libc/test/include/complex_test.cpp @@ -17,3 +17,22 @@ TEST(LlvmLibcComplexTest, VersionMacro) { TEST(LlvmLibcComplexTest, IMacro) { EXPECT_CFP_EQ(1.0fi, I); } TEST(LlvmLibcComplexTest, _Complex_IMacro) { EXPECT_CFP_EQ(1.0fi, _Complex_I); } + +TEST(LlvmLibcComplexTest, CMPLXMacro) { + EXPECT_CFP_EQ(CMPLX(0, 1.0), I); + EXPECT_CFP_EQ(CMPLX(1.0, 0), 1.0); + EXPECT_CFP_EQ(CMPLXF(0, 1.0f), I); + EXPECT_CFP_EQ(CMPLXF(1.0f, 0), 1.0f); + EXPECT_CFP_EQ(CMPLXL(0, 1.0l), I); + EXPECT_CFP_EQ(CMPLXL(1.0l, 0), 1.0l); + +#ifdef LIBC_TYPES_HAS_CFLOAT16 + EXPECT_CFP_EQ(CMPLXF16(0, 1.0), I); + EXPECT_CFP_EQ(CMPLXF16(1.0, 0), 1.0); +#endif // LIBC_TYPES_HAS_CFLOAT16 + +#ifdef LIBC_TYPES_HAS_CFLOAT128 + EXPECT_CFP_EQ(CMPLXF128(0, 1.0), I); + EXPECT_CFP_EQ(CMPLXF128(1.0, 0), 1.0); +#endif // LIBC_TYPES_HAS_CFLOAT128 +}