Skip to content

Commit

Permalink
[libc][math] Move str method from FPBits class to testing utils.
Browse files Browse the repository at this point in the history
str method of FPBits class is only used for pretty printing its objects
in tests.  It brings cpp::string dependency to FPBits class, which is not ideal
for embedded use case.  We move str method to a free function in test utils and
remove this dependency of FPBits class.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D152607
  • Loading branch information
lntue committed Jun 10, 2023
1 parent 361464c commit 37458f6
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 151 deletions.
16 changes: 14 additions & 2 deletions libc/src/__support/FPUtil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,25 @@ add_header_library(
.platform_defs
.float_properties
libc.src.__support.builtin_wrappers
libc.src.__support.integer_to_string
libc.src.__support.CPP.bit
libc.src.__support.CPP.string
libc.src.__support.CPP.type_traits
libc.src.__support.common
)

add_header_library(
fpbits_str
HDRS
fpbits_str.h
DEPENDS
.float_properties
.fp_bits
libc.src.__support.CPP.bit
libc.src.__support.CPP.type_traits
libc.src.__support.macros.attributes
libc.src.__support.common
libc.src.__support.integer_to_string
)

add_header_library(
nearest_integer_operations
HDRS
Expand Down
43 changes: 0 additions & 43 deletions libc/src/__support/FPUtil/FPBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@
#include "PlatformDefs.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/string.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/builtin_wrappers.h"
#include "src/__support/common.h"
#include "src/__support/integer_to_string.h"

#include "FloatProperties.h"
#include <stdint.h>
Expand Down Expand Up @@ -215,47 +213,6 @@ template <typename T> struct FPBits {
result.set_mantissa(mantissa);
return result;
}

// Converts the bits to a string in the following format:
// "0x<NNN...N> = S: N, E: 0xNNNN, M:0xNNN...N"
// 1. N is a hexadecimal digit.
// 2. The hexadecimal number on the LHS is the raw numerical representation
// of the bits.
// 3. The exponent is always 16 bits wide irrespective of the type of the
// floating encoding.
LIBC_INLINE cpp::string str() const {
if (is_nan())
return "(NaN)";
if (is_inf())
return get_sign() ? "(-Infinity)" : "(+Infinity)";

auto zerofill = [](char *arr, size_t n) {
for (size_t i = 0; i < n; ++i)
arr[i] = '0';
};

cpp::string s("0x");
char bitsbuf[IntegerToString::hex_bufsize<UIntType>()];
zerofill(bitsbuf, sizeof(bitsbuf));
IntegerToString::hex(bits, bitsbuf, false);
s += cpp::string(bitsbuf, sizeof(bitsbuf));

s += " = (";
s += cpp::string("S: ") + (get_sign() ? "1" : "0");

char expbuf[IntegerToString::hex_bufsize<uint16_t>()];
zerofill(expbuf, sizeof(expbuf));
IntegerToString::hex(get_unbiased_exponent(), expbuf, false);
s += cpp::string(", E: 0x") + cpp::string(expbuf, sizeof(expbuf));

char mantbuf[IntegerToString::hex_bufsize<UIntType>()] = {'0'};
zerofill(mantbuf, sizeof(mantbuf));
IntegerToString::hex(get_mantissa(), mantbuf, false);
s += cpp::string(", M: 0x") + cpp::string(mantbuf, sizeof(mantbuf));

s += ")";
return s;
}
};

} // namespace fputil
Expand Down
71 changes: 71 additions & 0 deletions libc/src/__support/FPUtil/fpbits_str.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//===------ Pretty print function for FPBits --------------------*- 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_FPUTIL_FP_BITS_STR_H
#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_FP_BITS_STR_H

#include "src/__support/CPP/string.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/FloatProperties.h"
#include "src/__support/integer_to_string.h"
#include "src/__support/macros/attributes.h"

namespace __llvm_libc {

// Converts the bits to a string in the following format:
// "0x<NNN...N> = S: N, E: 0xNNNN, M:0xNNN...N"
// 1. N is a hexadecimal digit.
// 2. The hexadecimal number on the LHS is the raw numerical representation
// of the bits.
// 3. The exponent is always 16 bits wide irrespective of the type of the
// floating encoding.
template <typename T> LIBC_INLINE cpp::string str(fputil::FPBits<T> x) {
using UIntType = typename fputil::FPBits<T>::UIntType;

if (x.is_nan())
return "(NaN)";
if (x.is_inf())
return x.get_sign() ? "(-Infinity)" : "(+Infinity)";

auto zerofill = [](char *arr, size_t n) {
for (size_t i = 0; i < n; ++i)
arr[i] = '0';
};

cpp::string s("0x");
char bitsbuf[IntegerToString::hex_bufsize<UIntType>()];
zerofill(bitsbuf, sizeof(bitsbuf));
IntegerToString::hex(x.bits, bitsbuf, false);
s += cpp::string(bitsbuf, sizeof(bitsbuf));

s += " = (";
s += cpp::string("S: ") + (x.get_sign() ? "1" : "0");

char expbuf[IntegerToString::hex_bufsize<uint16_t>()];
zerofill(expbuf, sizeof(expbuf));
IntegerToString::hex(x.get_unbiased_exponent(), expbuf, false);
s += cpp::string(", E: 0x") + cpp::string(expbuf, sizeof(expbuf));

if constexpr (cpp::is_same_v<T, long double> &&
fputil::FloatProperties<long double>::MANTISSA_WIDTH == 63) {
s += cpp::string(", I: ") + (x.get_implicit_bit() ? "1" : "0");
}

char mantbuf[IntegerToString::hex_bufsize<UIntType>()] = {'0'};
zerofill(mantbuf, sizeof(mantbuf));
IntegerToString::hex(x.get_mantissa(), mantbuf, false);
s += cpp::string(", M: 0x") + cpp::string(mantbuf, sizeof(mantbuf));

s += ")";
return s;
}

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FP_BITS_STR_H
46 changes: 0 additions & 46 deletions libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@
#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_X86_64_LONG_DOUBLE_BITS_H

#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/string.h"
#include "src/__support/UInt128.h"
#include "src/__support/common.h"
#include "src/__support/integer_to_string.h"
#include "src/__support/macros/properties/architectures.h"

#if !defined(LIBC_TARGET_ARCH_IS_X86)
Expand Down Expand Up @@ -209,50 +207,6 @@ template <> struct FPBits<long double> {
result.set_mantissa(mantissa);
return result;
}

// Converts the bits to a string in the following format:
// "0x<NNN...N> = S: N, E: 0xNNNN, I: N, M:0xNNN...N"
// 1. N is a hexadecimal digit.
// 2. "I" denotes the implicit bit.
// 3. The hexadecimal number on the LHS is the raw numerical representation
// of the bits.
// 4. The exponent is always 16 bits wide irrespective of the type of the
// floating encoding.
LIBC_INLINE cpp::string str() const {
if (is_nan())
return "(NaN)";
if (is_inf())
return get_sign() ? "(-Infinity)" : "(+Infinity)";

auto zerofill = [](char *arr, size_t n) {
for (size_t i = 0; i < n; ++i)
arr[i] = '0';
};

cpp::string s("0x");
char bitsbuf[IntegerToString::hex_bufsize<UIntType>()] = {'0'};
zerofill(bitsbuf, sizeof(bitsbuf));
IntegerToString::hex(bits, bitsbuf, false);
s += cpp::string(bitsbuf, sizeof(bitsbuf));

s += " = (";
s += cpp::string("S: ") + (get_sign() ? "1" : "0");

char expbuf[IntegerToString::hex_bufsize<uint16_t>()] = {'0'};
zerofill(expbuf, sizeof(expbuf));
IntegerToString::hex(get_unbiased_exponent(), expbuf, false);
s += cpp::string(", E: 0x") + cpp::string(expbuf, sizeof(expbuf));

s += cpp::string(", I: ") + (get_implicit_bit() ? "1" : "0");

char mantbuf[IntegerToString::hex_bufsize<UIntType>()] = {'0'};
zerofill(mantbuf, sizeof(mantbuf));
IntegerToString::hex(get_mantissa(), mantbuf, false);
s += cpp::string(", M: 0x") + cpp::string(mantbuf, sizeof(mantbuf));

s += ")";
return s;
}
};

static_assert(
Expand Down
2 changes: 1 addition & 1 deletion libc/test/UnitTest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ add_unittest_framework_library(
LibcTest
libc.test.UnitTest.string_utils
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.fpbits_str
libc.src.__support.FPUtil.fenv_impl
libc.test.UnitTest.string_utils
)

add_unittest_framework_library(
Expand Down
5 changes: 3 additions & 2 deletions libc/test/UnitTest/ErrnoSetterMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLVM_LIBC_TEST_ERRNOSETTERMATCHER_H

#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/fpbits_str.h"
#include "src/__support/StringUtil/error_to_string.h"
#include "src/__support/macros/properties/architectures.h"
#include "src/errno/libc_errno.h"
Expand Down Expand Up @@ -46,10 +47,10 @@ template <typename T> class ErrnoSetterMatcher : public Matcher<T> {
if constexpr (cpp::is_floating_point_v<T>) {
__llvm_libc::testing::tlog
<< "Expected return value to be: "
<< __llvm_libc::fputil::FPBits<T>(ExpectedReturn).str() << '\n';
<< str(__llvm_libc::fputil::FPBits<T>(ExpectedReturn)) << '\n';
__llvm_libc::testing::tlog
<< " But got: "
<< __llvm_libc::fputil::FPBits<T>(ActualReturn).str() << '\n';
<< str(__llvm_libc::fputil::FPBits<T>(ActualReturn)) << '\n';
} else {
__llvm_libc::testing::tlog << "Expected return value to be "
<< ExpectedReturn << " but got "
Expand Down
7 changes: 4 additions & 3 deletions libc/test/UnitTest/FPMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/fpbits_str.h"
#include "test/UnitTest/RoundingModeUtils.h"
#include "test/UnitTest/StringUtils.h"
#include "test/UnitTest/Test.h"
Expand All @@ -24,7 +25,7 @@ template <typename T, TestCond Condition> class FPMatcher : public Matcher<T> {
static_assert(cpp::is_floating_point_v<T>,
"FPMatcher can only be used with floating point values.");
static_assert(Condition == TestCond::EQ || Condition == TestCond::NE,
"Unsupported FPMathcer test condition.");
"Unsupported FPMatcher test condition.");

T expected;
T actual;
Expand All @@ -48,8 +49,8 @@ template <typename T, TestCond Condition> class FPMatcher : public Matcher<T> {

void explainError() override {
tlog << "Expected floating point value: "
<< fputil::FPBits<T>(expected).str() << '\n';
tlog << "Actual floating point value: " << fputil::FPBits<T>(actual).str()
<< str(fputil::FPBits<T>(expected)) << '\n';
tlog << "Actual floating point value: " << str(fputil::FPBits<T>(actual))
<< '\n';
}
};
Expand Down
1 change: 1 addition & 0 deletions libc/test/src/__support/FPUtil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ add_libc_test(
fpbits_test.cpp
DEPENDS
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.fpbits_str
)
Loading

0 comments on commit 37458f6

Please sign in to comment.