-
Notifications
You must be signed in to change notification settings - Fork 12k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc][stdfix] Add abs functions for signed fixed point types. #81823
Conversation
@llvm/pr-subscribers-libc Author: None (lntue) ChangesThis depends on #81819. Patch is 42.82 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/81823.diff 33 Files Affected:
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 33f6e97af0e183..69912d3b32f030 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -442,6 +442,18 @@ if(LIBC_COMPILER_HAS_FLOAT128)
)
endif()
+if(LIBC_COMPILER_HAS_FIXED_POINT)
+ list(APPEND TARGET_LIBM_ENTRYPOINTS
+ # stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.abshk
+ libc.src.stdfix.abshr
+ libc.src.stdfix.absk
+ libc.src.stdfix.absr
+ libc.src.stdfix.abslk
+ libc.src.stdfix.abslr
+ )
+endif()
+
if(LLVM_LIBC_FULL_BUILD)
list(APPEND TARGET_LIBC_ENTRYPOINTS
# assert.h entrypoints
diff --git a/libc/docs/math/stdfix.rst b/libc/docs/math/stdfix.rst
index 85d721b358f5ec..d05e3fdeabf1c5 100644
--- a/libc/docs/math/stdfix.rst
+++ b/libc/docs/math/stdfix.rst
@@ -60,7 +60,7 @@ Fixed-point Arithmetics
| +----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| | unsigned (uhr) | signed (hr) | unsigned (ur) | signed (r) | unsigned (ulr) | signed (lr) | unsigned (uhk) | signed (hk) | unsigned (uk) | signed (k) | unsigned (ulk) | signed (lk) |
+===============+================+=============+===============+============+================+=============+================+=============+===============+============+================+=============+
-| abs | | | | | | | | | | | | |
+| abs | | |check| | | |check| | | |check| | | |check| | | |check| | | |check| |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| bits\* | | | | | | | | | | | | |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index aebf4955382862..8d761764c22277 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -55,6 +55,23 @@ def UnsignedShortType : NamedType<"unsigned short">;
// TODO: Add compatibility layer to use C23 type _Float128 if possible.
def Float128Type : NamedType<"float128">;
+// Fixed point types.
+// From ISO/IEC TR 18037:2008 standard:
+// https://standards.iso.org/ittf/PubliclyAvailableStandards/c051126_ISO_IEC_TR_18037_2008.zip
+def ShortFractType : NamedType<"short fract">;
+def FractType : NamedType<"fract">;
+def LongFractType : NamedType<"long fract">;
+def UnsignedShortFractType : NamedType<"unsigned short fract">;
+def UnsignedFractType : NamedType<"unsigned fract">;
+def UnsignedLongFractType : NamedType<"unsigned long fract">;
+
+def ShortAccumType : NamedType<"short accum">;
+def AccumType : NamedType<"accum">;
+def LongAccumType : NamedType<"long accum">;
+def UnsignedShortAccumType : NamedType<"unsigned short accum">;
+def UnsignedAccumType : NamedType<"unsigned accum">;
+def UnsignedLongAccumType : NamedType<"unsigned long accum">;
+
// Common types
def VoidPtr : PtrType<VoidType>;
def VoidPtrPtr : PtrType<VoidPtr>;
diff --git a/libc/spec/stdc_ext.td b/libc/spec/stdc_ext.td
index 4a5b74f7bdc364..8af9624e532733 100644
--- a/libc/spec/stdc_ext.td
+++ b/libc/spec/stdc_ext.td
@@ -7,6 +7,13 @@ def StdcExt : StandardSpec<"stdc_ext"> {
[], // types
[], // enums
[ // functions
+ GuardedFunctionSpec<"abshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"absr", RetValSpec<FractType>, [ArgSpec<FractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"abslr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+ GuardedFunctionSpec<"abshk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"absk", RetValSpec<AccumType>, [ArgSpec<AccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"abslk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
]
>;
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 5211db7bc1f993..09b16be1e2d42e 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -6,6 +6,7 @@ add_subdirectory(fenv)
add_subdirectory(inttypes)
add_subdirectory(math)
add_subdirectory(stdbit)
+add_subdirectory(stdfix)
add_subdirectory(stdio)
add_subdirectory(stdlib)
add_subdirectory(string)
diff --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt
index 644cbff37aaade..4dac9b33325adb 100644
--- a/libc/src/__support/fixed_point/CMakeLists.txt
+++ b/libc/src/__support/fixed_point/CMakeLists.txt
@@ -5,4 +5,16 @@ add_header_library(
DEPENDS
libc.include.llvm-libc-macros.stdfix_macros
libc.src.__support.macros.attributes
+ libc.src.__support.CPP.type_traits
+)
+
+add_header_library(
+ fx_bits
+ HDRS
+ fx_bits.h
+ DEPENDS
+ .fx_rep
+ libc.include.llvm-libc-macros.stdfix_macros
+ libc.src.__support.macros.attributes
+ libc.src.__support.macros.optimization
)
diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
new file mode 100644
index 00000000000000..ad3a6fc97c0a1f
--- /dev/null
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -0,0 +1,37 @@
+//===-- 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_FXBITS_H
+#define LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+#include "fx_rep.h"
+
+#ifdef LIBC_COMPILER_HAS_FIXED_POINT
+
+namespace LIBC_NAMESPACE::fixed_point {
+
+template <typename T> LIBC_INLINE constexpr T abs(T x) {
+ using FXRep = FXRep<T>;
+ if constexpr (FXRep::SIGN_LEN == 0)
+ return x;
+ else {
+ if (LIBC_UNLIKELY(x == FXRep::MIN()))
+ return FXRep::MAX();
+ return (x < FXRep::ZERO() ? -x : x);
+ }
+}
+
+} // namespace LIBC_NAMESPACE::fixed_point
+
+#endif // LIBC_COMPILER_HAS_FIXED_POINT
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXBITS_H
diff --git a/libc/src/__support/fixed_point/fx_rep.h b/libc/src/__support/fixed_point/fx_rep.h
index 88cba3c95c6656..fcd7554c4d8550 100644
--- a/libc/src/__support/fixed_point/fx_rep.h
+++ b/libc/src/__support/fixed_point/fx_rep.h
@@ -10,144 +10,245 @@
#define LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXREP_H
#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
+#include <stdint.h>
+
#ifdef LIBC_COMPILER_HAS_FIXED_POINT
namespace LIBC_NAMESPACE::fixed_point {
+namespace internal {
+
+template <int Bits> struct Storage {
+ static_assert(Bits > 0 && Bits <= 64, "Bits has to be between 1 and 64.");
+ using Type = typename cpp::conditional_t<
+ (Bits <= 8), uint8_t,
+ typename cpp::conditional_t<
+ (Bits <= 16 && Bits > 8), uint16_t,
+ typename cpp::conditional_t<(Bits <= 32 && Bits > 16), uint32_t,
+ uint64_t>>>;
+};
+
+} // namespace internal
+
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_signed_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_unsigned_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_signed_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_unsigned_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_signed_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_unsigned_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_signed_t<StorageType>;
};
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 INTEGRAL_LEN = USACCUM_IBIT;
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USACCUM_FBIT;
+ LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_unsigned_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_signed_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_unsigned_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_signed_t<StorageType>;
};
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_VAR static constexpr int TOTAL_LEN =
+ SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+
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; }
+
+ using StorageType = typename internal::Storage<TOTAL_LEN>::Type;
+ using CompType = cpp::make_unsigned_t<StorageType>;
};
template <> struct FXRep<short sat fract> : FXRep<short fract> {};
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
new file mode 100644
index 00000000000000..1eaf64bb82a21b
--- /dev/null
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -0,0 +1,18 @@
+if(NOT LIBC_COMPILER_HAS_FIXED_POINT)
+ return()
+endif()
+
+foreach(suffix IN ITEMS hr r lr hk k lk)
+ add_entrypoint_object(
+ abs${suffix}
+ HDRS
+ abs${suffix}.h
+ SRCS
+ abs${suffix}.cpp
+ COMPILE_OPTIONS
+ -O3
+ -ffixed-point
+ DEPENDS
+ libc.src.__support.fixed_point.fx_bits
+ )
+endforeach()
diff --git a/libc/src/stdfix/abshk.cpp b/libc/src/stdfix/abshk.cpp
new file mode 100644
index 00000000000000..d76a5e64e61079
--- /dev/null
+++ b/libc/src/stdfix/abshk.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of abshk function ----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "abshk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(short accum, abshk, (short accum x)) {
+ return fixed_point::abs(x);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/abshk.h b/libc/src/stdfix/abshk.h
new file mode 100644
index 00000000000000..13c9300caab883
--- /dev/null
+++ b/libc/src/stdfix/abshk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for abshk -------------------------*- 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_STDFIX_ABSHK_H
+#define LLVM_LIBC_SRC_STDFIX_ABSHK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+short accum abshk(short accum x);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ABSHK_H
diff --git a/libc/src/stdfix/abshr.cpp b/libc/src/stdfix/abshr.cpp
new file mode 100644
index 00000000000000..db887046b662cd
--- /dev/null
+++ b/libc/src/stdfix/abshr.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of abshr function ----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "abshr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNC...
[truncated]
|
@@ -7,6 +7,13 @@ def StdcExt : StandardSpec<"stdc_ext"> { | |||
[], // types | |||
[], // enums | |||
[ // functions | |||
GuardedFunctionSpec<"abshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given that these are in stdfix.h, would it be reasonable to assume that the compiler has fixed point support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should still put it in the guards, since the types still require specific compiler flag, and if the stdfix.h
is included somewhere transitively in the users' codes where it's not being used, and they cannot easily control the header inclusions, it will force the users to add the compiler flag, or a hard compile errors.
By keeping the guards here, users can explicitly control when to enable it with the compiler flags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in that case can we add a #warning
to stdfix.h for if they don't have fixed point available?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to add that, because right now, if users try to use fixed point types / functions / macros without the compile flag, it will be a hard compile error. And if we add the warnings, users will keep seeing them even if they don't use it and got it transitively. And in a worse scenario, where they try to build with -Werror
, those warnings will become hard errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, we can discuss the comment after if you want.
No description provided.