Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,7 @@ set(TARGET_LIBM_ENTRYPOINTS
if(LIBC_COMPILER_HAS_FLOAT128)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# math.h C23 _Float128 entrypoints
# Temporarily disabled since float128 isn't working on the aarch64 buildbot
# libc.src.math.fabsf128
libc.src.math.fabsf128
)
endif()

Expand Down
2 changes: 1 addition & 1 deletion libc/config/linux/api.td
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def IntTypesAPI : PublicAPI<"inttypes.h"> {
}

def MathAPI : PublicAPI<"math.h"> {
let Types = ["double_t", "float_t"];
let Types = ["double_t", "float_t", "float128"];
}

def FenvAPI: PublicAPI<"fenv.h"> {
Expand Down
1 change: 1 addition & 0 deletions libc/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ add_gen_header(
.llvm-libc-macros.math_macros
.llvm-libc-types.double_t
.llvm-libc-types.float_t
.llvm-libc-types.float128
)

# TODO: This should be conditional on POSIX networking being included.
Expand Down
7 changes: 7 additions & 0 deletions libc/include/llvm-libc-types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,10 @@ add_header(ENTRY HDR ENTRY.h)
add_header(struct_hsearch_data HDR struct_hsearch_data.h)
add_header(struct_epoll_event HDR struct_epoll_event.h)
add_header(struct_epoll_data HDR struct_epoll_data.h)
add_header(
float128
HDR
float128.h
DEPENDS
libc.include.llvm-libc-macros.float_macros
)
31 changes: 31 additions & 0 deletions libc/include/llvm-libc-types/float128.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===-- Definition of float128 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_TYPES_FLOAT128_H__
#define __LLVM_LIBC_TYPES_FLOAT128_H__

#include <include/llvm-libc-macros/float-macros.h> // LDBL_MANT_DIG

// TODO: https://github.com/llvm/llvm-project/issues/80195
// Check _Float128 C23 type detection again when clang supports it.
#if defined(__STDC_IEC_60559_BFP__) && !defined(__clang__)
// Use _Float128 C23 type.
#define LIBC_COMPILER_HAS_C23_FLOAT128
typedef _Float128 float128;
#elif defined(__FLOAT128__)
// Use __float128 type.
// clang uses __FLOAT128__ macro to notify the availability of __float128 type:
// https://reviews.llvm.org/D15120
#define LIBC_COMPILER_HAS_FLOAT128_EXTENSION
typedef __float128 float128;
#elif (LDBL_MANT_DIG == 113)
// Use long double.
typedef long double float128;
#endif
Copy link
Member

@nickdesaulniers nickdesaulniers Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argh, sorry for causing confusion here, but I do think we'll benefit in the long run by documenting the state of the world.

So some issues we've found:

  • gcc did not support _Float128 in C mode until gcc-7, and C++ mode until gcc-13.
  • gcc defines __STDC_IEC_60559_BFP__ to 201404L so we cannot compare __STDC_IEC_60559_BFP__ to 202311L (at least doing so won't work for any compiler TODAY). Just having this one check would be ideal, but alas.
  • clang doesn't support _Float128.
  • glibc will define __STDC_IEC_60559_BFP__ to 201404L, so we can't use it to detect compiler support in overlay mode (or not without great pain).

So perhaps we can have:

// GCC did not support _Float128 in C mode until gcc-7, or C++ mode until g++-13.
#if defined(__GNUC__) && !defined(clang) && \
    (defined(__cpluscplus) && __GNUC__ >= 13) || \
    (!defined(__cplusplus) && __GNUC__ >= 7)
#define LIBC_COMPILER_HAS_C23_FLOAT128
#endif

// TODO: replace when clang has actual _Float128 support.
// https://github.com/llvm/llvm-project/issues/80195
#ifdef __clang__
#define LIBC_COMPILER_HAS_FLOAT128_EXTENSION
#endif

#ifdef LIBC_COMPILER_HAS_C23_FLOAT128
typedef _Float128 float128;
#elif defined(LIBC_COMPILER_HAS_FLOAT128_EXTENSION)
typedef __float128 float128;
#elif LDBL_MANT_DIG == 113
typedef long double float128;
#else
#error "no f128 support"
#endif

I was hopefully naive that we could just have:

#if __STDC_IEC_60559_BFP__ < 202311L
#error "no _Float128 support"
#endif

Copy link
Contributor Author

@lntue lntue Feb 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me summarize the current support in the following table:

                    |     clang      |   gcc pre-13   |     gcc-13     |   g++ pre-13   |     g++-13     |
----------------------------------------------------------------------------------------------------------
                    | x86-64 | arm64 | x86-64 | arm64 | x86-64 | arm64 | x86-64 | arm64 | x86-64 | arm64 |
----------------------------------------------------------------------------------------------------------
_Float128           |        |       |    X   |   X   |    X   |   X   |        |       |    X   |   X   |
----------------------------------------------------------------------------------------------------------
__float128          |    X   |       |    X   |       |    X   |       |    X   |       |    X   |       |
----------------------------------------------------------------------------------------------------------
long double as f128 |        |   X   |        |   X   |        |   X   |        |   X   |        |   X   |

So far the cleanest check I found without relying on compiler versioning or target architecture is follow:

#if defined(__STDC_IEC_60559_BFP__) && !defined(__clang__) && !defined(__cplusplus)
#define LIBC_COMPILER_HAS_C23_FLOAT128
#elif defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
#define LIBC_COMPILER_HAS_FLOAT128_EXTENSION
#elif (LDBL_MANT_DIG == 113)
// Use long double.
#define LIBC_LONG_DOUBLE_IS_FLOAT128
#endif

#ifdef LIBC_COMPILER_HAS_C23_FLOAT128
typedef _Float128 float128;
#elif defined(LIBC_COMPILER_HAS_FLOAT128_EXTENSION)
typedef __float128 float128;
#elif defined(LIBC_LONG_DOUBLE_IS_FLOAT128)
typedef long double float128;
#endif

with comments / TODO to revisit the conditions in the future when clang has support for _Float128.
WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM; we'll hopefully be revisiting this block of preprocessor checks when compilers improve their support. Let's get the build back to green.


#endif // __LLVM_LIBC_TYPES_FLOAT128_H__
2 changes: 1 addition & 1 deletion libc/spec/spec.td
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def UnsignedCharType : NamedType<"unsigned char">;
def UnsignedShortType : NamedType<"unsigned short">;

// TODO: Add compatibility layer to use C23 type _Float128 if possible.
def Float128Type : NamedType<"__float128">;
def Float128Type : NamedType<"float128">;

// Common types
def VoidPtr : PtrType<VoidType>;
Expand Down
1 change: 1 addition & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ def StdC : StandardSpec<"stdc"> {
[
NamedType<"float_t">,
NamedType<"double_t">,
NamedType<"float128">,
],
[], // Enumerations
[
Expand Down
2 changes: 2 additions & 0 deletions libc/src/__support/macros/properties/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ add_header_library(
.compiler
.cpu_features
.os
libc.include.llvm-libc-macros.float_macros
libc.include.llvm-libc-types.float128
)
24 changes: 2 additions & 22 deletions libc/src/__support/macros/properties/float.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_FLOAT_H
#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_FLOAT_H

#include "include/llvm-libc-macros/float-macros.h" // LDBL_MANT_DIG
#include "include/llvm-libc-types/float128.h" // float128
#include "src/__support/macros/properties/architectures.h"
#include "src/__support/macros/properties/compiler.h"
#include "src/__support/macros/properties/cpu_features.h"
#include "src/__support/macros/properties/os.h"

#include <float.h> // LDBL_MANT_DIG

// 'long double' properties.
#if (LDBL_MANT_DIG == 53)
#define LIBC_LONG_DOUBLE_IS_FLOAT64
Expand Down Expand Up @@ -53,26 +53,6 @@ using float16 = _Float16;
#endif

// float128 support.
#if (defined(LIBC_COMPILER_GCC_VER) && (LIBC_COMPILER_GCC_VER >= 1301)) && \
(defined(LIBC_TARGET_ARCH_IS_AARCH64) || \
defined(LIBC_TARGET_ARCH_IS_ANY_RISCV) || \
defined(LIBC_TARGET_ARCH_IS_X86_64))
#define LIBC_COMPILER_HAS_C23_FLOAT128
#endif
#if (defined(LIBC_COMPILER_CLANG_VER) && (LIBC_COMPILER_CLANG_VER >= 600)) && \
(defined(LIBC_TARGET_ARCH_IS_X86_64) && \
defined(LIBC_TARGET_OS_IS_LINUX) && !defined(LIBC_TARGET_OS_IS_FUCHSIA))
#define LIBC_COMPILER_HAS_FLOAT128_EXTENSION
#endif

#if defined(LIBC_COMPILER_HAS_C23_FLOAT128)
using float128 = _Float128;
#elif defined(LIBC_COMPILER_HAS_FLOAT128_EXTENSION)
using float128 = __float128;
#elif defined(LIBC_LONG_DOUBLE_IS_FLOAT128)
using float128 = long double;
#endif

#if defined(LIBC_COMPILER_HAS_C23_FLOAT128) || \
defined(LIBC_COMPILER_HAS_FLOAT128_EXTENSION) || \
defined(LIBC_LONG_DOUBLE_IS_FLOAT128)
Expand Down