[libc-commits] [libc] [libc][stdfix] Add FXRep helper class for fixed point types. (PR #81272)
via libc-commits
libc-commits at lists.llvm.org
Fri Feb 9 08:41:05 PST 2024
https://github.com/lntue created https://github.com/llvm/llvm-project/pull/81272
This PR depends on https://github.com/llvm/llvm-project/pull/81255.
>From 61cc872d0cee10a071255fc68a188ac40accf102 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 9 Feb 2024 15:20:31 +0000
Subject: [PATCH 1/2] [libc][stdfix] Generate stdfix.h header with fixed point
precision macros according to N1169 standard, and add fixed point type
support detection.
---
.../cmake/modules/CheckCompilerFeatures.cmake | 11 +-
.../compiler_features/check_fixed_point.cpp | 5 +
libc/config/linux/x86_64/headers.txt | 1 +
libc/include/CMakeLists.txt | 8 +
libc/include/llvm-libc-macros/CMakeLists.txt | 6 +
libc/include/llvm-libc-macros/stdfix-macros.h | 352 ++++++++++++++++++
libc/include/stdfix.h.def | 20 +
libc/spec/stdc.td | 10 +
libc/test/include/stdfix_test.cpp | 80 ++++
9 files changed, 491 insertions(+), 2 deletions(-)
create mode 100644 libc/cmake/modules/compiler_features/check_fixed_point.cpp
create mode 100644 libc/include/llvm-libc-macros/stdfix-macros.h
create mode 100644 libc/include/stdfix.h.def
create mode 100644 libc/test/include/stdfix_test.cpp
diff --git a/libc/cmake/modules/CheckCompilerFeatures.cmake b/libc/cmake/modules/CheckCompilerFeatures.cmake
index 983ce86ab1b253..333b3afe2ad8c2 100644
--- a/libc/cmake/modules/CheckCompilerFeatures.cmake
+++ b/libc/cmake/modules/CheckCompilerFeatures.cmake
@@ -3,7 +3,7 @@
# ------------------------------------------------------------------------------
# Initialize ALL_COMPILER_FEATURES as empty list.
-set(ALL_COMPILER_FEATURES "float128")
+set(ALL_COMPILER_FEATURES "float128" "fixed_point")
# Making sure ALL_COMPILER_FEATURES is sorted.
list(SORT ALL_COMPILER_FEATURES)
@@ -42,16 +42,23 @@ set(AVAILABLE_COMPILER_FEATURES "")
# Try compile a C file to check if flag is supported.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
foreach(feature IN LISTS ALL_COMPILER_FEATURES)
+ set(compile_options ${LIBC_COMPILE_OPTIONS_NATIVE})
+ if(${feature} STREQUAL "fixed_point")
+ list(APPEND compiler_options "-ffixed-point")
+ endif()
+
try_compile(
has_feature
${CMAKE_CURRENT_BINARY_DIR}/compiler_features
SOURCES ${LIBC_SOURCE_DIR}/cmake/modules/compiler_features/check_${feature}.cpp
- COMPILE_DEFINITIONS -I${LIBC_SOURCE_DIR} ${LIBC_COMPILE_OPTIONS_NATIVE}
+ COMPILE_DEFINITIONS -I${LIBC_SOURCE_DIR} ${compiler_options}
)
if(has_feature)
list(APPEND AVAILABLE_COMPILER_FEATURES ${feature})
if(${feature} STREQUAL "float128")
set(LIBC_COMPILER_HAS_FLOAT128 TRUE)
+ elseif(${feature} STREQUAL "fixed_point")
+ set(LIBC_COMPILER_HAS_FIXED_POINT TRUE)
endif()
endif()
endforeach()
diff --git a/libc/cmake/modules/compiler_features/check_fixed_point.cpp b/libc/cmake/modules/compiler_features/check_fixed_point.cpp
new file mode 100644
index 00000000000000..02932dbf4d722d
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_fixed_point.cpp
@@ -0,0 +1,5 @@
+#include "include/llvm-libc-macross/stdfix_macros.h"
+
+#ifndef LIBC_COMPILER_HAS_FIXED_POINT
+#error unsupported
+#endif
diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index 8f37cf9f30f8d0..d0c662c2bc072e 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -16,6 +16,7 @@ set(TARGET_PUBLIC_HEADERS
libc.include.spawn
libc.include.setjmp
libc.include.stdbit
+ libc.include.stdfix
libc.include.stdio
libc.include.stdlib
libc.include.string
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 332410453b54d1..5882d03593a54e 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -104,6 +104,14 @@ add_gen_header(
.llvm-libc-types.float128
)
+add_gen_header(
+ stdfix
+ DEF_FILE stdfix.h.def
+ GEN_HDR stdfix.h
+ DEPENDS
+ .llvm-libc-macros.stdfix_macros
+)
+
# TODO: This should be conditional on POSIX networking being included.
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/arpa)
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 562769a5e84cef..225885d3a9b085 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -227,3 +227,9 @@ add_macro_header(
HDR
inttypes-macros.h
)
+
+add_macro_header(
+ stdfix_macros
+ HDR
+ stdfix-macros.h
+)
diff --git a/libc/include/llvm-libc-macros/stdfix-macros.h b/libc/include/llvm-libc-macros/stdfix-macros.h
new file mode 100644
index 00000000000000..fdca60cdd35cbe
--- /dev/null
+++ b/libc/include/llvm-libc-macros/stdfix-macros.h
@@ -0,0 +1,352 @@
+//===-- Definitions from stdfix.h -----------------------------------------===//
+//
+// 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_STDFIX_MACROS_H
+#define __LLVM_LIBC_MACROS_STDFIX_MACROS_H
+
+#ifdef __clang__
+#if (!defined(__cplusplus) || (__clang_major__ >= 18))
+// _Fract and _Accum types are avaiable
+#define LIBC_COMPILER_HAS_FIXED_POINT
+#endif // __cplusplus
+#endif // __clang__
+
+#ifdef LIBC_COMPILER_HAS_FIXED_POINT
+
+#define fract _Fract
+#define accum _Accum
+
+// Default values: from N1169 standard - Annex A.3 - Typical desktop processor.
+
+#ifdef __SFRACT_FBIT__
+#define SFRACT_FBIT __SFRACT_FBIT__
+#else
+#define SFRACT_FBIT 7
+#endif // SFRACT_FBIT
+
+#ifdef __SFRACT_MIN__
+#define SFRACT_MIN __SFRACT_MIN__
+#else
+#define SFRACT_MIN (-0.5HR - 0.5HR)
+#endif // SFRACT_MIN
+
+#ifdef __SFRACT_MAX__
+#define SFRACT_MAX __SFRACT_MAX__
+#else
+#define SFRACT_MAX 0x1.FCp-1HR
+#endif // SFRACT_MAX
+
+#ifdef __SFRACT_EPSILON__
+#define SFRACT_EPSILON __SFRACT_EPSILON__
+#else
+#define SFRACT_EPSILON 0x1.0p-7HR
+#endif // SFRACT_EPSILON
+
+#ifdef __USFRACT_FBIT__
+#define USFRACT_FBIT __USFRACT_FBIT__
+#else
+#define USFRACT_FBIT 8
+#endif // USFRACT_FBIT
+
+#ifdef __USFRACT_MIN__
+#define USFRACT_MIN __USFRACT_MIN__
+#else
+#define USFRACT_MIN 0.0UHR
+#endif // USFRACT_MIN
+
+#ifdef __USFRACT_MAX__
+#define USFRACT_MAX __USFRACT_MAX__
+#else
+#define USFRACT_MAX 0x1.FEp-1UHR
+#endif // USFRACT_MAX
+
+#ifdef __USFRACT_EPSILON__
+#define USFRACT_EPSILON __USFRACT_EPSILON__
+#else
+#define USFRACT_EPSILON 0x1.0p-8UHR
+#endif // USFRACT_EPSILON
+
+#ifdef __FRACT_FBIT__
+#define FRACT_FBIT __FRACT_FBIT__
+#else
+#define FRACT_FBIT 15
+#endif // FRACT_FBIT
+
+#ifdef __FRACT_MIN__
+#define FRACT_MIN __FRACT_MIN__
+#else
+#define FRACT_MIN (-0.5R - 0.5R)
+#endif // FRACT_MIN
+
+#ifdef __FRACT_MAX__
+#define FRACT_MAX __FRACT_MAX__
+#else
+#define FRACT_MAX 0x1.FFFCp-1R
+#endif // FRACT_MAX
+
+#ifdef __FRACT_EPSILON__
+#define FRACT_EPSILON __FRACT_EPSILON__
+#else
+#define FRACT_EPSILON 0x1.0p-15R
+#endif // FRACT_EPSILON
+
+#ifdef __UFRACT_FBIT__
+#define UFRACT_FBIT __UFRACT_FBIT__
+#else
+#define UFRACT_FBIT 16
+#endif // UFRACT_FBIT
+
+#ifdef __UFRACT_MIN__
+#define UFRACT_MIN __UFRACT_MIN__
+#else
+#define UFRACT_MIN 0.0UR
+#endif // UFRACT_MIN
+
+#ifdef __UFRACT_MAX__
+#define UFRACT_MAX __UFRACT_MAX__
+#else
+#define UFRACT_MAX 0x1.FFFEp-1UR
+#endif // UFRACT_MAX
+
+#ifdef __UFRACT_EPSILON__
+#define UFRACT_EPSILON __UFRACT_EPSILON__
+#else
+#define UFRACT_EPSILON 0x1.0p-16UR
+#endif // UFRACT_EPSILON
+
+#ifdef __LFRACT_FBIT__
+#define LFRACT_FBIT __LFRACT_FBIT__
+#else
+#define LFRACT_FBIT 31
+#endif // LFRACT_FBIT
+
+#ifdef __LFRACT_MIN__
+#define LFRACT_MIN __LFRACT_MIN__
+#else
+#define LFRACT_MIN (-0.5LR - 0.5LR)
+#endif // LFRACT_MIN
+
+#ifdef __LFRACT_MAX__
+#define LFRACT_MAX __LFRACT_MAX__
+#else
+#define LFRACT_MAX 0x1.FFFFFFFCp-1LR
+#endif // LFRACT_MAX
+
+#ifdef __LFRACT_EPSILON__
+#define LFRACT_EPSILON __LFRACT_EPSILON__
+#else
+#define LFRACT_EPSILON 0x1.0p-31LR
+#endif // LFRACT_EPSILON
+
+#ifdef __ULFRACT_FBIT__
+#define ULFRACT_FBIT __ULFRACT_FBIT__
+#else
+#define ULFRACT_FBIT 32
+#endif // ULFRACT_FBIT
+
+#ifdef __ULFRACT_MIN__
+#define ULFRACT_MIN __ULFRACT_MIN__
+#else
+#define ULFRACT_MIN 0.0ULR
+#endif // ULFRACT_MIN
+
+#ifdef __ULFRACT_MAX__
+#define ULFRACT_MAX __ULFRACT_MAX__
+#else
+#define ULFRACT_MAX 0x1.FFFFFFFEp-1ULR
+#endif // ULFRACT_MAX
+
+#ifdef __ULFRACT_EPSILON__
+#define ULFRACT_EPSILON __ULFRACT_EPSILON__
+#else
+#define ULFRACT_EPSILON 0x1.0p-32ULR
+#endif // ULFRACT_EPSILON
+
+#ifdef __SACCUM_FBIT__
+#define SACCUM_FBIT __SACCUM_FBIT__
+#else
+#define SACCUM_FBIT 7
+#endif // SACCUM_FBIT
+
+#ifdef __SACCUM_IBIT__
+#define SACCUM_IBIT __SACCUM_IBIT__
+#else
+#define SACCUM_IBIT 8
+#endif // SACCUM_IBIT
+
+#ifdef __SACCUM_MIN__
+#define SACCUM_MIN __SACCUM_MIN__
+#else
+#define SACCUM_MIN (-0x1.0p+7HK - 0x1.0p+7HK)
+#endif // SACCUM_MIN
+
+#ifdef __SACCUM_MAX__
+#define SACCUM_MAX __SACCUM_MAX__
+#else
+#define SACCUM_MAX 0x1.FFFCp+7HK
+#endif // SACCUM_MAX
+
+#ifdef __SACCUM_EPSILON__
+#define SACCUM_EPSILON __SACCUM_EPSILON__
+#else
+#define SACCUM_EPSILON 0x1.0p-7HK
+#endif // SACCUM_EPSILON
+
+#ifdef __USACCUM_FBIT__
+#define USACCUM_FBIT __USACCUM_FBIT__
+#else
+#define USACCUM_FBIT 8
+#endif // USACCUM_FBIT
+
+#ifdef __USACCUM_IBIT__
+#define USACCUM_IBIT __USACCUM_IBIT__
+#else
+#define USACCUM_IBIT 8
+#endif // USACCUM_IBIT
+
+#ifdef __USACCUM_MIN__
+#define USACCUM_MIN __USACCUM_MIN__
+#else
+#define USACCUM_MIN 0.0UHK
+#endif // USACCUM_MIN
+
+#ifdef __USACCUM_MAX__
+#define USACCUM_MAX __USACCUM_MAX__
+#else
+#define USACCUM_MAX 0x1.FFFEp+7UHK
+#endif // USACCUM_MAX
+
+#ifdef __USACCUM_EPSILON__
+#define USACCUM_EPSILON __USACCUM_EPSILON__
+#else
+#define USACCUM_EPSILON 0x1.0p-8UHK
+#endif // USACCUM_EPSILON
+
+#ifdef __ACCUM_FBIT__
+#define ACCUM_FBIT __ACCUM_FBIT__
+#else
+#define ACCUM_FBIT 15
+#endif // ACCUM_FBIT
+
+#ifdef __ACCUM_IBIT__
+#define ACCUM_IBIT __ACCUM_IBIT__
+#else
+#define ACCUM_IBIT 16
+#endif // ACCUM_IBIT
+
+#ifdef __ACCUM_MIN__
+#define ACCUM_MIN __ACCUM_MIN__
+#else
+#define ACCUM_MIN (-0x1.0p+15K - 0x1.0p+15K)
+#endif // ACCUM_MIN
+
+#ifdef __ACCUM_MAX__
+#define ACCUM_MAX __ACCUM_MAX__
+#else
+#define ACCUM_MAX 0x1.FFFFFFFCp+15K
+#endif // ACCUM_MAX
+
+#ifdef __ACCUM_EPSILON__
+#define ACCUM_EPSILON __ACCUM_EPSILON__
+#else
+#define ACCUM_EPSILON 0x1.0p-15K
+#endif // ACCUM_EPSILON
+
+#ifdef __UACCUM_FBIT__
+#define UACCUM_FBIT __UACCUM_FBIT__
+#else
+#define UACCUM_FBIT 16
+#endif // UACCUM_FBIT
+
+#ifdef __UACCUM_IBIT__
+#define UACCUM_IBIT __UACCUM_IBIT__
+#else
+#define UACCUM_IBIT 16
+#endif // UACCUM_IBIT
+
+#ifdef __UACCUM_MIN__
+#define UACCUM_MIN __UACCUM_MIN__
+#else
+#define UACCUM_MIN 0.0UK
+#endif // UACCUM_MIN
+
+#ifdef __UACCUM_MAX__
+#define UACCUM_MAX __UACCUM_MAX__
+#else
+#define UACCUM_MAX 0x1.FFFFFFFEp+15UK
+#endif // UACCUM_MAX
+
+#ifdef __UACCUM_EPSILON__
+#define UACCUM_EPSILON __UACCUM_EPSILON__
+#else
+#define UACCUM_EPSILON 0x1.0p-16UK
+#endif // UACCUM_EPSILON
+
+#ifdef __LACCUM_FBIT__
+#define LACCUM_FBIT __LACCUM_FBIT__
+#else
+#define LACCUM_FBIT 31
+#endif // LACCUM_FBIT
+
+#ifdef __LACCUM_IBIT__
+#define LACCUM_IBIT __LACCUM_IBIT__
+#else
+#define LACCUM_IBIT 32
+#endif // LACCUM_IBIT
+
+#ifdef __LACCUM_MIN__
+#define LACCUM_MIN __LACCUM_MIN__
+#else
+#define LACCUM_MIN (-0x1.0p+31LK - 0x1.0p+31LK)
+#endif // LACCUM_MIN
+
+#ifdef __LACCUM_MAX__
+#define LACCUM_MAX __LACCUM_MAX__
+#else
+#define LACCUM_MAX 0x1.FFFFFFFFFFFFFFFCp+31LK
+#endif // LACCUM_MAX
+
+#ifdef __LACCUM_EPSILON__
+#define LACCUM_EPSILON __LACCUM_EPSILON__
+#else
+#define LACCUM_EPSILON 0x1.0p-31LK
+#endif // LACCUM_EPSILON
+
+#ifdef __ULACCUM_FBIT__
+#define ULACCUM_FBIT __ULACCUM_FBIT__
+#else
+#define ULACCUM_FBIT 32
+#endif // ULACCUM_FBIT
+
+#ifdef __ULACCUM_IBIT__
+#define ULACCUM_IBIT __ULACCUM_IBIT__
+#else
+#define ULACCUM_IBIT 32
+#endif // ULACCUM_IBIT
+
+#ifdef __ULACCUM_MIN__
+#define ULACCUM_MIN __ULACCUM_MIN__
+#else
+#define ULACCUM_MIN 0.0ULK
+#endif // ULACCUM_MIN
+
+#ifdef __ULACCUM_MAX__
+#define ULACCUM_MAX __ULACCUM_MAX__
+#else
+#define ULACCUM_MAX 0x1.FFFFFFFFFFFFFFFEp+31ULK
+#endif // ULACCUM_MAX
+
+#ifdef __ULACCUM_EPSILON__
+#define ULACCUM_EPSILON __ULACCUM_EPSILON__
+#else
+#define ULACCUM_EPSILON 0x1.0p-32ULK
+#endif // ULACCUM_EPSILON
+
+#endif // LIBC_COMPILER_HAS_FIXED_POINT
+
+#endif // __LLVM_LIBC_MACROS_STDFIX_MACROS_H
diff --git a/libc/include/stdfix.h.def b/libc/include/stdfix.h.def
new file mode 100644
index 00000000000000..74c177d1ac4ef6
--- /dev/null
+++ b/libc/include/stdfix.h.def
@@ -0,0 +1,20 @@
+//===-- C standard library header stdfix.h --------------------------------===//
+//
+// 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_STDFIX_H
+#define LLVM_LIBC_STDFIX_H
+
+#include <__llvm-libc-common.h>
+#include <llvm-libc-macros/stdfix-macros.h>
+
+// From N1169 standard:
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf
+
+%%public_api()
+
+#endif // LLVM_LIBC_STDFIX_H
\ No newline at end of file
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index e37f95a7c2daf0..822c9ca1999a2c 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -898,6 +898,15 @@ def StdC : StandardSpec<"stdc"> {
]
>;
+ HeaderSpec StdFix = HeaderSpec<
+ "stdfix.h",
+ [], // macros
+ [], // types
+ [], // enums
+ [ // functions
+ ]
+ >;
+
HeaderSpec Limits = HeaderSpec<"limits.h">;
NamedType SigAtomicT = NamedType<"sig_atomic_t">;
@@ -1207,6 +1216,7 @@ def StdC : StandardSpec<"stdc"> {
Math,
String,
StdBit,
+ StdFix,
StdIO,
StdLib,
IntTypes,
diff --git a/libc/test/include/stdfix_test.cpp b/libc/test/include/stdfix_test.cpp
new file mode 100644
index 00000000000000..8d5d4c162938ec
--- /dev/null
+++ b/libc/test/include/stdfix_test.cpp
@@ -0,0 +1,80 @@
+//===-- Unittests for stdbit ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "test/UnitTest/Test.h"
+
+/*
+ * The intent of this test is validate that:
+ * 1. We provide the definition of the various type generic macros of stdbit.h
+ * (the macros are transitively included from stdbit-macros.h by stdbit.h).
+ * 2. It dispatches to the correct underlying function.
+ * Because unit tests build without public packaging, the object files produced
+ * do not contain non-namespaced symbols.
+ */
+
+/*
+ * Declare these BEFORE including stdbit-macros.h so that this test may still be
+ * run even if a given target doesn't yet have these individual entrypoints
+ * enabled.
+ */
+extern "C" {
+unsigned stdc_leading_zeros_uc(unsigned char) noexcept { return 0xAAU; }
+unsigned stdc_leading_zeros_us(unsigned short) noexcept { return 0xABU; }
+unsigned stdc_leading_zeros_ui(unsigned) noexcept { return 0xACU; }
+unsigned stdc_leading_zeros_ul(unsigned long) noexcept { return 0xADU; }
+unsigned stdc_leading_zeros_ull(unsigned long long) noexcept { return 0xAFU; }
+unsigned stdc_leading_ones_uc(unsigned char) noexcept { return 0xBAU; }
+unsigned stdc_leading_ones_us(unsigned short) noexcept { return 0xBBU; }
+unsigned stdc_leading_ones_ui(unsigned) noexcept { return 0xBCU; }
+unsigned stdc_leading_ones_ul(unsigned long) noexcept { return 0xBDU; }
+unsigned stdc_leading_ones_ull(unsigned long long) noexcept { return 0xBFU; }
+unsigned stdc_trailing_zeros_uc(unsigned char) noexcept { return 0xCAU; }
+unsigned stdc_trailing_zeros_us(unsigned short) noexcept { return 0xCBU; }
+unsigned stdc_trailing_zeros_ui(unsigned) noexcept { return 0xCCU; }
+unsigned stdc_trailing_zeros_ul(unsigned long) noexcept { return 0xCDU; }
+unsigned stdc_trailing_zeros_ull(unsigned long long) noexcept { return 0xCFU; }
+unsigned stdc_trailing_ones_uc(unsigned char) noexcept { return 0xDAU; }
+unsigned stdc_trailing_ones_us(unsigned short) noexcept { return 0xDBU; }
+unsigned stdc_trailing_ones_ui(unsigned) noexcept { return 0xDCU; }
+unsigned stdc_trailing_ones_ul(unsigned long) noexcept { return 0xDDU; }
+unsigned stdc_trailing_ones_ull(unsigned long long) noexcept { return 0xDFU; }
+}
+
+#include "include/llvm-libc-macros/stdbit-macros.h"
+
+TEST(LlvmLibcStdbitTest, TypeGenericMacroLeadingZeros) {
+ EXPECT_EQ(stdc_leading_zeros(static_cast<unsigned char>(0U)), 0xAAU);
+ EXPECT_EQ(stdc_leading_zeros(static_cast<unsigned short>(0U)), 0xABU);
+ EXPECT_EQ(stdc_leading_zeros(0U), 0xACU);
+ EXPECT_EQ(stdc_leading_zeros(0UL), 0xADU);
+ EXPECT_EQ(stdc_leading_zeros(0ULL), 0xAFU);
+}
+
+TEST(LlvmLibcStdbitTest, TypeGenericMacroLeadingOnes) {
+ EXPECT_EQ(stdc_leading_ones(static_cast<unsigned char>(0U)), 0xBAU);
+ EXPECT_EQ(stdc_leading_ones(static_cast<unsigned short>(0U)), 0xBBU);
+ EXPECT_EQ(stdc_leading_ones(0U), 0xBCU);
+ EXPECT_EQ(stdc_leading_ones(0UL), 0xBDU);
+ EXPECT_EQ(stdc_leading_ones(0ULL), 0xBFU);
+}
+
+TEST(LlvmLibcStdbitTest, TypeGenericMacroTrailingZeros) {
+ EXPECT_EQ(stdc_trailing_zeros(static_cast<unsigned char>(0U)), 0xCAU);
+ EXPECT_EQ(stdc_trailing_zeros(static_cast<unsigned short>(0U)), 0xCBU);
+ EXPECT_EQ(stdc_trailing_zeros(0U), 0xCCU);
+ EXPECT_EQ(stdc_trailing_zeros(0UL), 0xCDU);
+ EXPECT_EQ(stdc_trailing_zeros(0ULL), 0xCFU);
+}
+
+TEST(LlvmLibcStdbitTest, TypeGenericMacroTrailingOnes) {
+ EXPECT_EQ(stdc_trailing_ones(static_cast<unsigned char>(0U)), 0xDAU);
+ EXPECT_EQ(stdc_trailing_ones(static_cast<unsigned short>(0U)), 0xDBU);
+ EXPECT_EQ(stdc_trailing_ones(0U), 0xDCU);
+ EXPECT_EQ(stdc_trailing_ones(0UL), 0xDDU);
+ EXPECT_EQ(stdc_trailing_ones(0ULL), 0xDFU);
+}
>From 8fe518df2f1bc411bf74bbbd7aedd0a404f6c131 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 9 Feb 2024 16:37:37 +0000
Subject: [PATCH 2/2] [libc][stdfix] Add FXRep helper class for fixed point
types.
---
libc/src/__support/CMakeLists.txt | 2 +
libc/src/__support/fixed_point/CMakeLists.txt | 8 +
libc/src/__support/fixed_point/fx_rep.h | 157 ++++++++++++++++++
3 files changed, 167 insertions(+)
create mode 100644 libc/src/__support/fixed_point/CMakeLists.txt
create mode 100644 libc/src/__support/fixed_point/fx_rep.h
diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index bd814a080c4f87..290cc465b1125a 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -271,3 +271,5 @@ add_subdirectory(threads)
add_subdirectory(File)
add_subdirectory(HashTable)
+
+add_subdirectory(fixed_point)
diff --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt
new file mode 100644
index 00000000000000..644cbff37aaade
--- /dev/null
+++ b/libc/src/__support/fixed_point/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_header_library(
+ fx_rep
+ HDRS
+ fx_rep.h
+ DEPENDS
+ libc.include.llvm-libc-macros.stdfix_macros
+ libc.src.__support.macros.attributes
+)
diff --git a/libc/src/__support/fixed_point/fx_rep.h b/libc/src/__support/fixed_point/fx_rep.h
new file mode 100644
index 00000000000000..b05f0cd2764e14
--- /dev/null
+++ b/libc/src/__support/fixed_point/fx_rep.h
@@ -0,0 +1,157 @@
+//===-- Utility class to manipulate fixed point numbers. --*- C++ -*-=========//
+//
+// 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_SRC___SUPPORT_FIXEDPOINT_FXREP_H
+#define LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXREP_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
+
+#ifdef LIBC_COMPILER_HAS_FIXED_POINT
+
+namespace LIBC_NAMESPACE::fixed_point {
+
+template <typename T> struct FXRep;
+
+template <> struct FXRep<short fract> {
+ using Type = short _Fract;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SFRACT_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return SFRACT_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return SFRACT_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0HR; }
+ LIBC_INLINE static constexpr Type EPS() { return SFRACT_EPSILON; }
+};
+
+template <> struct FXRep<unsigned short fract> {
+ using Type = unsigned short fract;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USFRACT_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return USFRACT_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return USFRACT_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0UHR; }
+ LIBC_INLINE static constexpr Type EPS() { return USFRACT_EPSILON; }
+};
+
+template <> struct FXRep<fract> {
+ using Type = fract;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = FRACT_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return FRACT_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return FRACT_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0R; }
+ LIBC_INLINE static constexpr Type EPS() { return FRACT_EPSILON; }
+};
+
+template <> struct FXRep<unsigned fract> {
+ using Type = unsigned fract;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UFRACT_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return UFRACT_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return UFRACT_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0UR; }
+ LIBC_INLINE static constexpr Type EPS() { return UFRACT_EPSILON; }
+};
+
+template <> struct FXRep<long fract> {
+ using Type = long fract;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LFRACT_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return LFRACT_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return LFRACT_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0LR; }
+ LIBC_INLINE static constexpr Type EPS() { return LFRACT_EPSILON; }
+};
+
+template <> struct FXRep<unsigned long fract> {
+ using Type = unsigned long fract;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULFRACT_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return ULFRACT_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0ULR; }
+ LIBC_INLINE static constexpr Type EPS() { return ULFRACT_EPSILON; }
+};
+
+template <> struct FXRep<short accum> {
+ using Type = short accum;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = SACCUM_IBIT;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SACCUM_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return SACCUM_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return SACCUM_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0HK; }
+ LIBC_INLINE static constexpr Type EPS() { return SACCUM_EPSILON; }
+};
+
+template <> struct FXRep<unsigned short accum> {
+ using Type = unsigned short accum;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = UACCUM_IBIT;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USACCUM_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return USACCUM_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return USACCUM_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0UHK; }
+ LIBC_INLINE static constexpr Type EPS() { return USACCUM_EPSILON; }
+};
+
+template <> struct FXRep<accum> {
+ using Type = accum;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ACCUM_IBIT;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ACCUM_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return ACCUM_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return ACCUM_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0K; }
+ LIBC_INLINE static constexpr Type EPS() { return ACCUM_EPSILON; }
+};
+
+template <> struct FXRep<unsigned accum> {
+ using Type = unsigned accum;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = UACCUM_IBIT;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UACCUM_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return UACCUM_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return UACCUM_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0UK; }
+ LIBC_INLINE static constexpr Type EPS() { return UACCUM_EPSILON; }
+};
+
+template <> struct FXRep<long accum> {
+ using Type = long accum;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = LACCUM_IBIT;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LACCUM_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return LACCUM_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return LACCUM_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0LK; }
+ LIBC_INLINE static constexpr Type EPS() { return LACCUM_EPSILON; }
+};
+
+template <> struct FXRep<unsigned long accum> {
+ using Type = unsigned long accum;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+ LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ULACCUM_IBIT;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULACCUM_FBIT;
+ LIBC_INLINE static constexpr Type MIN() { return ULACCUM_MIN; }
+ LIBC_INLINE static constexpr Type MAX() { return ULACCUM_MIN; }
+ LIBC_INLINE static constexpr Type ZERO() { return 0.0ULK; }
+ LIBC_INLINE static constexpr Type EPS() { return ULACCUM_EPSILON; }
+};
+
+} // namespace LIBC_NAMESPACE::fixed_point
+
+#endif // LIBC_COMPILER_HAS_FIXED_POINT
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXREP_H
More information about the libc-commits
mailing list