[flang] Template specializations and more automatic configuration
Original-commit: flang-compiler/f18@a230a53907 Reviewed-on: https://github.com/flang-compiler/f18/pull/101 Tree-same-pre-rewrite: false
This commit is contained in:
parent
d0c120b371
commit
ce91eae382
|
|
@ -14,4 +14,5 @@
|
|||
|
||||
add_library(FortranEvaluate
|
||||
constant.cc
|
||||
integer.cc
|
||||
)
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef FORTRAN_EVALUATE_COMMON_H_
|
||||
#define FORTRAN_EVALUATE_COMMON_H_
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
namespace Fortran::evaluate {
|
||||
|
||||
// Integers are always ordered; reals may not be.
|
||||
enum class Ordering { Less, Equal, Greater };
|
||||
enum class Relation { Less, Equal, Greater, Unordered };
|
||||
|
||||
static constexpr Ordering Reverse(Ordering ordering) {
|
||||
if (ordering == Ordering::Less) {
|
||||
return Ordering::Greater;
|
||||
} else if (ordering == Ordering::Greater) {
|
||||
return Ordering::Less;
|
||||
} else {
|
||||
return Ordering::Equal;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr Relation Reverse(Relation relation) {
|
||||
if (relation == Relation::Less) {
|
||||
return Relation::Greater;
|
||||
} else if (relation == Relation::Greater) {
|
||||
return Relation::Less;
|
||||
} else {
|
||||
return relation;
|
||||
}
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
constexpr bool IsHostLittleEndian{false};
|
||||
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
constexpr bool IsHostLittleEndian{true};
|
||||
#else
|
||||
#error host endianness is not known
|
||||
#endif
|
||||
|
||||
template<bool LE8, bool LE16, bool LE32, bool LE64> struct SmallestUInt {};
|
||||
template<> struct SmallestUInt<true, true, true, true> {
|
||||
using type = std::uint8_t;
|
||||
};
|
||||
template<> struct SmallestUInt<false, true, true, true> {
|
||||
using type = std::uint16_t;
|
||||
};
|
||||
template<> struct SmallestUInt<false, false, true, true> {
|
||||
using type = std::uint32_t;
|
||||
};
|
||||
template<> struct SmallestUInt<false, false, false, true> {
|
||||
using type = std::uint64_t;
|
||||
};
|
||||
template<int BITS>
|
||||
using HostUnsignedInt =
|
||||
typename SmallestUInt<BITS <= 8, BITS <= 16, BITS <= 32, BITS <= 64>::type;
|
||||
|
||||
} // namespace Fortran::evaluate
|
||||
#endif // FORTRAN_EVALUATE_COMMON_H_
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "integer.h"
|
||||
|
||||
namespace Fortran::evaluate {
|
||||
|
||||
template class Integer<8>;
|
||||
template class Integer<16>;
|
||||
template class Integer<32>;
|
||||
template class Integer<64>;
|
||||
template class Integer<128>;
|
||||
|
||||
// Sanity checks intended to catch misconfiguration bugs
|
||||
static_assert(Integer<8>::partBits == 8);
|
||||
static_assert(std::is_same_v<typename Integer<8>::Part, std::uint8_t>);
|
||||
static_assert(Integer<16>::partBits == 16);
|
||||
static_assert(std::is_same_v<typename Integer<16>::Part, std::uint16_t>);
|
||||
static_assert(Integer<32>::partBits == 32);
|
||||
static_assert(std::is_same_v<typename Integer<32>::Part, std::uint32_t>);
|
||||
static_assert(Integer<64>::partBits == 32);
|
||||
static_assert(std::is_same_v<typename Integer<64>::Part, std::uint32_t>);
|
||||
static_assert(Integer<128>::partBits == 32);
|
||||
static_assert(std::is_same_v<typename Integer<128>::Part, std::uint32_t>);
|
||||
|
||||
} // namespace Fortran::evaluate
|
||||
|
|
@ -24,47 +24,42 @@
|
|||
// and signed-magnitude encodings appear to be extinct in 2018.)
|
||||
|
||||
#include "bit-population-count.h"
|
||||
#include "common.h"
|
||||
#include "leading-zero-bit-count.h"
|
||||
#include <cinttypes>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Fortran::evaluate {
|
||||
|
||||
// Integers are always ordered.
|
||||
enum class Ordering { Less, Equal, Greater };
|
||||
|
||||
static constexpr Ordering Reverse(Ordering ordering) {
|
||||
if (ordering == Ordering::Less) {
|
||||
return Ordering::Greater;
|
||||
} else if (ordering == Ordering::Greater) {
|
||||
return Ordering::Less;
|
||||
} else {
|
||||
return Ordering::Equal;
|
||||
}
|
||||
}
|
||||
|
||||
// Implements an integer as an assembly of smaller integer parts.
|
||||
// For best performance, the part should be half of the size of the
|
||||
// largest efficient integer supported by the host processor.
|
||||
// Implements an integer as an assembly of smaller host integer parts
|
||||
// that constitute the digits of a large-radix fixed-point number.
|
||||
// For best performance, the type of these parts should be half of the
|
||||
// size of the largest efficient integer supported by the host processor.
|
||||
// These parts are stored in either little- or big-endian order, which can
|
||||
// match that of the host's endianness or not; but if the ordering matches
|
||||
// that of the host, raw host data can be overlaid with a properly configured
|
||||
// instance of this class and used in situ.
|
||||
// To facilitate exhaustive testing of what would otherwise be more rare
|
||||
// edge cases, this class template may be configured to use other part
|
||||
// types &/or partial fields in the parts.
|
||||
// types &/or partial fields in the parts. The radix (i.e., the number
|
||||
// of possible values in a part), however, must be a power of two; this
|
||||
// template class is not generalized to enable, say, decimal arithmetic.
|
||||
// Member functions that correspond to Fortran intrinsic functions are
|
||||
// named accordingly.
|
||||
template<int BITS, int PARTBITS = 32, typename PART = std::uint32_t,
|
||||
typename BIGPART = std::uint64_t, bool LITTLE_ENDIAN = true>
|
||||
class Integer {
|
||||
// named accordingly so that they can be referenced easily in the
|
||||
// language standard.
|
||||
template<int BITS,
|
||||
int PARTBITS =
|
||||
BITS<32 ? BITS : 32, typename PART = HostUnsignedInt<PARTBITS>,
|
||||
typename BIGPART = HostUnsignedInt<PARTBITS * 2>,
|
||||
bool LITTLE_ENDIAN = IsHostLittleEndian> class Integer {
|
||||
public:
|
||||
static constexpr int bits{BITS};
|
||||
static constexpr int partBits{PARTBITS};
|
||||
using Part = PART;
|
||||
using BigPart = BIGPART;
|
||||
static_assert(sizeof(BigPart) >= 2 * sizeof(Part));
|
||||
static_assert(CHAR_BIT * sizeof(BigPart) >= 2 * partBits);
|
||||
static constexpr bool littleEndian{LITTLE_ENDIAN};
|
||||
|
||||
private:
|
||||
|
|
@ -152,9 +147,9 @@ public:
|
|||
if (bits < 4) {
|
||||
return 0;
|
||||
}
|
||||
Integer x{HUGE}, ten{std::uint64_t{10}};
|
||||
Integer x{HUGE()}, ten{std::uint64_t{10}};
|
||||
int digits{0};
|
||||
while (x.Compare(ten) != Ordering::Less) {
|
||||
while (x.CompareUnsigned(ten) != Ordering::Less) {
|
||||
++digits;
|
||||
x = x.DivideUnsigned(ten).quotient;
|
||||
}
|
||||
|
|
@ -515,8 +510,7 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
constexpr Integer MERGE_BITS(
|
||||
const Integer &y, const Integer &mask) const {
|
||||
constexpr Integer MERGE_BITS(const Integer &y, const Integer &mask) const {
|
||||
return IAND(mask).IOR(y.IAND(mask.NOT()));
|
||||
}
|
||||
|
||||
|
|
@ -585,7 +579,7 @@ public:
|
|||
constexpr ValueWithOverflow SIGN(const Integer &sign) const {
|
||||
bool goNegative{sign.IsNegative()};
|
||||
if (goNegative == IsNegative()) {
|
||||
return *this;
|
||||
return {*this, false};
|
||||
} else if (goNegative) {
|
||||
return Negate();
|
||||
} else {
|
||||
|
|
@ -655,8 +649,7 @@ public:
|
|||
Integer quotient, remainder;
|
||||
bool divisionByZero, overflow;
|
||||
};
|
||||
constexpr QuotientWithRemainder DivideUnsigned(
|
||||
const Integer &divisor) const {
|
||||
constexpr QuotientWithRemainder DivideUnsigned(const Integer &divisor) const {
|
||||
if (divisor.IsZero()) {
|
||||
return {MASKR(bits), Integer{}, true, false}; // overflow to max value
|
||||
}
|
||||
|
|
@ -734,7 +727,6 @@ public:
|
|||
// Result has the sign of the divisor argument.
|
||||
// 8 mod 5 = 3; -8 mod 5 = 2; 8 mod -5 = -2; -8 mod -5 = -3
|
||||
constexpr ValueWithOverflow MODULO(const Integer &divisor) const {
|
||||
Integer quotient{*this};
|
||||
bool negativeDivisor{divisor.IsNegative()};
|
||||
bool distinctSigns{IsNegative() != negativeDivisor};
|
||||
QuotientWithRemainder divided{DivideSigned(divisor)};
|
||||
|
|
@ -781,5 +773,14 @@ private:
|
|||
|
||||
Part part_[parts];
|
||||
};
|
||||
|
||||
extern template class Integer<8>;
|
||||
extern template class Integer<16>;
|
||||
extern template class Integer<32>;
|
||||
extern template class Integer<64>;
|
||||
extern template class Integer<128>;
|
||||
|
||||
template<int KIND> using IntrinsicInteger = Integer<KIND * CHAR_BIT>;
|
||||
|
||||
} // namespace Fortran::evaluate
|
||||
#endif // FORTRAN_EVALUATE_INTEGER_H_
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
|
|||
std::int64_t maxPositiveSignedValue{(std::int64_t{1} << (BITS - 1)) - 1};
|
||||
std::int64_t mostNegativeSignedValue{-(std::int64_t{1} << (BITS - 1))};
|
||||
char desc[64];
|
||||
std::snprintf(desc, sizeof desc, "BITS=%d, PARTBITS=%d, sizeof(Part)=%d, LE=%d",
|
||||
BITS, INT::partBits, static_cast<int>(sizeof(typename INT::Part)),
|
||||
INT::littleEndian);
|
||||
std::snprintf(desc, sizeof desc,
|
||||
"BITS=%d, PARTBITS=%d, sizeof(Part)=%d, LE=%d", BITS, INT::partBits,
|
||||
static_cast<int>(sizeof(typename INT::Part)), INT::littleEndian);
|
||||
|
||||
MATCH(BITS, INT::bits)(desc);
|
||||
MATCH(maxPositiveSignedValue, INT::HUGE().ToUInt64())(desc);
|
||||
|
|
@ -47,14 +47,14 @@ template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
|
|||
MATCH(x ^ maxUnsignedValue, t.ToUInt64())("%s, x=0x%llx", desc, x);
|
||||
auto negated{a.Negate()};
|
||||
MATCH(x == std::uint64_t{1} << (BITS - 1), negated.overflow)
|
||||
("%s, x=0x%llx", desc, x);
|
||||
("%s, x=0x%llx", desc, x);
|
||||
MATCH(-x & maxUnsignedValue, negated.value.ToUInt64())
|
||||
("%s, x=0x%llx", desc, x);
|
||||
("%s, x=0x%llx", desc, x);
|
||||
auto abs{a.ABS()};
|
||||
MATCH(x == std::uint64_t{1} << (BITS - 1), abs.overflow)
|
||||
("%s, x=0x%llx", desc, x);
|
||||
MATCH(x >> (BITS-1) ? -x & maxUnsignedValue : x, abs.value.ToUInt64())
|
||||
("%s, x=0x%llx", desc, x);
|
||||
("%s, x=0x%llx", desc, x);
|
||||
MATCH(x >> (BITS - 1) ? -x & maxUnsignedValue : x, abs.value.ToUInt64())
|
||||
("%s, x=0x%llx", desc, x);
|
||||
int lzbc{a.LEADZ()};
|
||||
COMPARE(lzbc, >=, 0)("%s, x=0x%llx", desc, x);
|
||||
COMPARE(lzbc, <=, BITS)("%s, x=0x%llx", desc, x);
|
||||
|
|
@ -77,7 +77,7 @@ template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
|
|||
MATCH(trailcheck, a.TRAILZ())("%s, x=0x%llx", desc, x);
|
||||
for (int j{0}; j < BITS; ++j) {
|
||||
MATCH((x >> j) & 1, a.BTEST(j))
|
||||
("%s, x=0x%llx, bit %d", desc, x, j);
|
||||
("%s, x=0x%llx, bit %d", desc, x, j);
|
||||
}
|
||||
// TODO test DIM, MODULO, ISHFTC, DSHIFTL/R
|
||||
// TODO test IBCLR, IBSET, IBITS, MAX, MIN, MERGE_BITS, RANGE, SIGN
|
||||
|
|
@ -104,20 +104,21 @@ template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
|
|||
for (int count{0}; count <= BITS + 1; ++count) {
|
||||
t = a.SHIFTL(count);
|
||||
MATCH((x << count) & maxUnsignedValue, t.ToUInt64())
|
||||
("%s, x=0x%llx, count=%d", desc, x, count);
|
||||
("%s, x=0x%llx, count=%d", desc, x, count);
|
||||
t = a.ISHFT(count);
|
||||
MATCH((x << count) & maxUnsignedValue, t.ToUInt64())
|
||||
("%s, x=0x%llx, count=%d", desc, x, count);
|
||||
("%s, x=0x%llx, count=%d", desc, x, count);
|
||||
t = a.SHIFTR(count);
|
||||
MATCH(x >> count, t.ToUInt64())
|
||||
("%s, x=0x%llx, count=%d", desc, x, count);
|
||||
("%s, x=0x%llx, count=%d", desc, x, count);
|
||||
t = a.ISHFT(-count);
|
||||
MATCH(x >> count, t.ToUInt64())("%s, x=0x%llx, count=%d", desc, x, count);
|
||||
t = a.SHIFTA(count);
|
||||
std::uint64_t fill{-(x >> (BITS-1))};
|
||||
std::uint64_t sra{count >= BITS ? fill : (x >> count) | (fill << (BITS-count))};
|
||||
std::uint64_t fill{-(x >> (BITS - 1))};
|
||||
std::uint64_t sra{
|
||||
count >= BITS ? fill : (x >> count) | (fill << (BITS - count))};
|
||||
MATCH(sra, t.ToInt64())
|
||||
("%s, x=0x%llx, count=%d", desc, x, count);
|
||||
("%s, x=0x%llx, count=%d", desc, x, count);
|
||||
}
|
||||
|
||||
for (std::uint64_t y{0}; y <= maxUnsignedValue; ++y) {
|
||||
|
|
@ -146,8 +147,8 @@ template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
|
|||
ord = Ordering::Equal;
|
||||
}
|
||||
TEST(a.CompareSigned(b) == ord)
|
||||
("%s, x=0x%llx %lld %d, y=0x%llx %lld %d", desc, x, sx,
|
||||
a.IsNegative(), y, sy, b.IsNegative());
|
||||
("%s, x=0x%llx %lld %d, y=0x%llx %lld %d", desc, x, sx, a.IsNegative(), y,
|
||||
sy, b.IsNegative());
|
||||
|
||||
t = a.IAND(b);
|
||||
MATCH(x & y, t.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
|
|
@ -156,41 +157,45 @@ template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
|
|||
t = a.IEOR(b);
|
||||
MATCH(x ^ y, t.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
auto sum{a.AddUnsigned(b)};
|
||||
COMPARE(x + y, ==, sum.value.ToUInt64() + (std::uint64_t{sum.carry} << BITS))
|
||||
("%s, x=0x%llx, y=0x%llx, carry=%d", desc, x, y, sum.carry);
|
||||
COMPARE(
|
||||
x + y, ==, sum.value.ToUInt64() + (std::uint64_t{sum.carry} << BITS))
|
||||
("%s, x=0x%llx, y=0x%llx, carry=%d", desc, x, y, sum.carry);
|
||||
auto ssum{a.AddSigned(b)};
|
||||
MATCH((sx + sy) & maxUnsignedValue, ssum.value.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(sx + sy < mostNegativeSignedValue ||
|
||||
sx + sy > maxPositiveSignedValue, ssum.overflow)
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(
|
||||
sx + sy < mostNegativeSignedValue || sx + sy > maxPositiveSignedValue,
|
||||
ssum.overflow)
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
auto diff{a.SubtractSigned(b)};
|
||||
MATCH((sx - sy) & maxUnsignedValue, diff.value.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(sx - sy < mostNegativeSignedValue ||
|
||||
sx - sy > maxPositiveSignedValue, diff.overflow)
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(
|
||||
sx - sy < mostNegativeSignedValue || sx - sy > maxPositiveSignedValue,
|
||||
diff.overflow)
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
auto product{a.MultiplyUnsigned(b)};
|
||||
MATCH(x * y, (product.upper.ToUInt64() << BITS) ^ product.lower.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx, lower=0x%llx, upper=0x%llx", desc, x, y,
|
||||
MATCH(
|
||||
x * y, (product.upper.ToUInt64() << BITS) ^ product.lower.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx, lower=0x%llx, upper=0x%llx", desc, x, y,
|
||||
product.lower.ToUInt64(), product.upper.ToUInt64());
|
||||
product = a.MultiplySigned(b);
|
||||
MATCH((sx * sy) & maxUnsignedValue, product.lower.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(((sx * sy) >> BITS) & maxUnsignedValue, product.upper.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
auto quot{a.DivideUnsigned(b)};
|
||||
MATCH(y == 0, quot.divisionByZero)("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
if (y == 0) {
|
||||
MATCH(maxUnsignedValue, quot.quotient.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(0, quot.remainder.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
} else {
|
||||
MATCH(x / y, quot.quotient.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(x % y, quot.remainder.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
}
|
||||
quot = a.DivideSigned(b);
|
||||
bool badCase{sx == mostNegativeSignedValue &&
|
||||
|
|
@ -206,16 +211,18 @@ template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
|
|||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
}
|
||||
MATCH(0, quot.remainder.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
} else if (badCase) {
|
||||
MATCH(x, quot.quotient.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(0, quot.remainder.ToUInt64())("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(x, quot.quotient.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
MATCH(0, quot.remainder.ToUInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
} else {
|
||||
MATCH(sx / sy, quot.quotient.ToInt64())
|
||||
("%s, x=0x%llx %lld, y=0x%llx %lld; unsigned 0x%llx", desc, x, sx, y,
|
||||
("%s, x=0x%llx %lld, y=0x%llx %lld; unsigned 0x%llx", desc, x, sx, y,
|
||||
sy, quot.quotient.ToUInt64());
|
||||
MATCH(sx - sy * (sx / sy), quot.remainder.ToInt64())
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
("%s, x=0x%llx, y=0x%llx", desc, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ FailureDetailPrinter Test(
|
|||
}
|
||||
}
|
||||
|
||||
FailureDetailPrinter Match(const char *file, int line,
|
||||
unsigned long long want, const char *gots, unsigned long long got) {
|
||||
FailureDetailPrinter Match(const char *file, int line, unsigned long long want,
|
||||
const char *gots, unsigned long long got) {
|
||||
if (want == got) {
|
||||
++passes;
|
||||
return BitBucket;
|
||||
|
|
@ -90,8 +90,8 @@ FailureDetailPrinter Compare(const char *file, int line, const char *xs,
|
|||
return BitBucket;
|
||||
} else {
|
||||
++failures;
|
||||
fprintf(stderr, "%s:%d: FAIL %s[0x%llx] %s %s[0x%llx]\n", file, line, xs,
|
||||
x, rel, ys, y);
|
||||
fprintf(stderr, "%s:%d: FAIL %s[0x%llx] %s %s[0x%llx]\n", file, line, xs, x,
|
||||
rel, ys, y);
|
||||
return PrintFailureDetails;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ int Complete();
|
|||
// will also print z after the usual failure message if x != y.
|
||||
#define TEST(predicate) \
|
||||
testing::Test(__FILE__, __LINE__, #predicate, (predicate))
|
||||
#define MATCH(want, got) \
|
||||
testing::Match(__FILE__, __LINE__, (want), #got, (got))
|
||||
#define MATCH(want, got) testing::Match(__FILE__, __LINE__, (want), #got, (got))
|
||||
#define COMPARE(x, rel, y) \
|
||||
testing::Compare(__FILE__, __LINE__, #x, #rel, #y, (x), (y))
|
||||
|
||||
|
|
@ -36,8 +35,8 @@ int Complete();
|
|||
using FailureDetailPrinter = void (*)(const char *, ...);
|
||||
FailureDetailPrinter Test(
|
||||
const char *file, int line, const char *predicate, bool pass);
|
||||
FailureDetailPrinter Match(const char *file, int line,
|
||||
unsigned long long want, const char *gots, unsigned long long got);
|
||||
FailureDetailPrinter Match(const char *file, int line, unsigned long long want,
|
||||
const char *gots, unsigned long long got);
|
||||
FailureDetailPrinter Compare(const char *file, int line, const char *xs,
|
||||
const char *rel, const char *ys, unsigned long long x,
|
||||
unsigned long long y);
|
||||
|
|
|
|||
Loading…
Reference in New Issue